text: // 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 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 }
  