// 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() }
