# ----------------------------------------------------------------------------
# Uma coletânea de funções matemáticas simples.
# Se o primeiro argumento for um '-p' seguido de número sem espaço
# define a precisão dos resultados ( casas decimais ), o padrão é 6
# Em cada função foi colocado um pequeno help um pouco mais detalhado,
# pois ficou muito extenso colocar no help do zzmat apenas.
#
# Funções matemáticas disponíveis.
# Aritméticas:               | Trigonométricas:
#  mmc    mdc                |  sen   cos   tan
#  media  soma  produto      |  csc   sec   cot
#  log    ln    raiz         |  asen  acos  atan
#  somatoria    produtoria
#  pow, potencia ou elevado
#
# Combinatória:        | Sequências:          | Funções:
#  fat                 |  pa  pa2  pg  lucas  |  area  volume  r3
#  arranjo  arranjo_r  |  fibonacci  ou fib   |  det   vetor   d2p
#  combinacao          |  tribonacci ou trib
#  combinacao_r        |  mersenne  recaman  collatz
#
# Equações:                  | Auxiliares:
#  eq2g  egr    err          |  abs  int
#  egc   egc3p  ege          |  sem_zeros
#  newton ou binomio_newton  |  aleatorio  random
#  conf_eq                   |  compara_num
#
# Mais detalhes: zzmat função
#
# Uso: zzmat [-pnumero] funções [número] [número]
# Ex.: zzmat mmc 8 12
#      zzmat media 5[2] 7 4[3]
#      zzmat somatoria 3 9 2x+3
#      zzmat -p3 sen 60g
#
# Autor: Itamar <itamarnet (a) yahoo com br>
# Desde: 2011-01-19
# Versão: 23
# Licença: GPL
# Requisitos: zzcalcula zzseq zzaleatorio zztrim zzconverte zztestar
# Tags: número, cálculo
# ----------------------------------------------------------------------------
zzmat ()
{
	zzzz -h mat "$1" && return

	local funcao num precisao
	local pi=3.1415926535897932384626433832795
	local LANG=en

	# Verificação dos parâmetros
	test -n "$1" || { zztool -e uso mat; return 1; }

	# Definindo a precisão dos resultados qdo é pertinente. Padrão é 6.
	echo "$1" | grep '^-p' >/dev/null
	if test "$?" = "0"
	then
		precisao="${1#-p}"
		zztestar numero $precisao || precisao="6"
		shift
	else
		precisao="6"
	fi

	funcao="$1"

	# Atalhos para funções pow e fat, usando operadores unários
	if zztool grep_var '^' "$funcao" && zztestar numero_real "${funcao%^*}" && zztestar numero_real "${funcao#*^}"
	then
		zzmat -p${precisao} pow "${funcao%^*}" "${funcao#*^}"
		return
	elif zztool grep_var '!' "$funcao" && zztestar numero "${funcao%\!}"
	then
		zzmat -p${precisao} fat "${funcao%\!}" $2
		return
	fi

	case "$funcao" in
	sem_zeros)
		# Elimina o zeros nao significativos
		local num1
		shift
		num1=$(zztool multi_stdin "$@" | tr ',' '.')
		num1=$(echo "$num1" | sed 's/^[[:blank:].0]*$/zero/;s/^[[:blank:]0]*//;s/zero/0/')
		if test $precisao -gt 0
			then
			echo "$num1" | grep '\.' > /dev/null
			if test "$?" = "0"
			then
				num1=$(echo "$num1" | sed 's/[0[:blank:]]*$//' | sed 's/\.$//')
			fi
		fi
		num1=$(echo "$num1" | sed 's/^\./0\./')
		echo "$num1"
	;;
	compara_num)
		if test $# -eq "3" && zztestar numero_real $2 && zztestar numero_real $3
		then
			local num1 num2
			num1=$(echo "$2" | tr ',' '.')
			num2=$(echo "$3" | tr ',' '.')
			echo "$num1 $num2" |
			awk '
				$1 > $2  { print "maior" }
				$1 == $2 { print "igual" }
				$1 < $2  { print "menor" }
			'
		else
			zztool erro " zzmat $funcao: Compara 2 numeros"
			zztool erro " Retorna o texto 'maior', 'menor' ou 'igual'"
			zztool erro " Uso: zzmat $funcao numero numero"
			return 1
		fi
	;;
	int)
		local num1
		if test '-h' = "$2"
		then
			zztool erro " zzmat $funcao: Valor Inteiro"
			zztool erro " Uso: zzmat $funcao numero"
			zztool erro "      echo numero | zzmat $funcao"
			return
		fi
		shift
		num1=$(zztool multi_stdin "$@" | tr ',' '.')
		if zztestar numero_real $num1
		then
			echo $num1 | sed 's/\..*$//'
		fi
	;;
	abs)
		local num1
		if test '-h' = "$2"
		then
			zztool erro " zzmat $funcao: Valor Absoluto"
			zztool erro " Uso: zzmat $funcao numero"
			zztool erro "      echo numero | zzmat $funcao"
			return
		fi
		shift
		num1=$(zztool multi_stdin "$@" | tr ',' '.')
		if zztestar numero_real $num1
		then
			echo "$num1" | sed 's/^[-+]//'
		fi
	;;
	sen | cos | tan | csc | sec | cot)
		if test $# -eq "2"
		then
			local num1 num2 ang
			num1=$(echo "$2" | sed 's/g$//; s/gr$//; s/rad$//' | tr , .)
			ang=$(echo "$2" | tr -d -c '[grad]')
			echo "$2" | grep -E '(g|rad|gr)$' >/dev/null
			if test "$?" -eq "0" && zztestar numero_real $num1
			then
				case $ang in
				g)   num2=$(zzconverte -p$((precisao+2)) gr $num1);;
				gr)  num2=$(zzconverte -p$((precisao+2)) ar $num1);;
				rad) num2=$num1;;
				esac

				case $funcao in
				sen) num1="scale=${precisao};s(${num2})" ;;
				cos) num1="scale=${precisao};c(${num2})" ;;
				tan)
					num1="scale=${precisao};if (c(${num2})) {s(${num2})/c(${num2})}" ;;
				sec)
					num1="scale=${precisao};if (c(${num2})) {1/c(${num2})}" ;;
				csc)
					num1="scale=${precisao};if (s(${num2})) {1/s(${num2})}" ;;
				cot)
					num1="scale=${precisao};if (s(${num2})) {c(${num2})/s(${num2})}" ;;
				esac

				test -n "$num1" && num="$num1"
			else
				echo " Uso: zzmat $funcao número(g|rad|gr) {graus|radianos|grado}"
			fi
		else
			zztool erro " zzmat Função Trigonométrica:
	sen: Seno
	cos: Cosseno
	tan: Tangente
	sec: Secante
	csc: Cossecante
	cot: Cotangente"
			zztool erro " Uso: zzmat $funcao número(g|rad|gr) {graus|radianos|grado}"
			return 1
		fi
	;;
	asen | acos | atan)
		if test $# -ge "2" && test $# -le "4" && zztestar numero_real $2
		then
			local num1 num2 num3 sinal
			num1=$(echo "$2" | tr ',' '.')
			test "$funcao" != "atan" && num2=$(awk 'BEGIN {if ('$num1'>1 || '$num1'<-1) print "erro"}')
			if test "$num2" = "erro"
			then
				zzmat $funcao -h >&2;return 1
			fi

			echo "$num1" | grep '^-' >/dev/null && sinal="-" || unset sinal
			num1=$(zzmat abs $num1)

			case $funcao in
			atan)
				num2=$(echo "a(${num1})" | bc -l)
				test -n "$sinal" && num2=$(echo "($pi)-($num2)" | bc -l)
				echo "$4" | grep '2' >/dev/null && num2=$(echo "($num2)+($pi)" | bc -l)
			;;
			asen)
				num3=$(echo "sqrt(1-${num1}^2)" | bc -l | awk '{printf "%.'${precisao}'f\n", $1}')
				if test "$num3" = $(printf '%.'${precisao}'f' 0 | tr ',' '.')
				then
					num2=$(echo "$pi/2" | bc -l)
				else
					num2=$(echo "a(${num1}/sqrt(1-${num1}^2))" | bc -l)
				fi
				echo "$4" | grep '2' >/dev/null && num2=$(echo "($pi)-($num2)" | bc -l)
				test -n "$sinal" && num2=$(echo "($pi)+($num2)" | bc -l)
			;;
			acos)
				num3=$(echo "$num1" | bc -l | awk '{printf "%.'${precisao}'f\n", $1}')
				if test "$num3" = $(printf '%.'${precisao}'f' 0 | tr ',' '.')
				then
					num2=$(echo "$pi/2" | bc -l)
				else
					num2=$(echo "a(sqrt(1-${num1}^2)/${num1})" | bc -l)
				fi
				test -n "$sinal" && num2=$(echo "($pi)-($num2)" | bc -l)
				echo "$4" | grep '2' >/dev/null && num2=$(echo "2*($pi)-($num2)" | bc -l)
			;;
			esac

			echo "$4" | grep 'r' >/dev/null && num2=$(echo "($num2)-2*($pi)" | bc -l)

			case $3 in
			g)        num=$(zzconverte -p$((precisao+2)) rg $num2);;
			gr)       num=$(zzconverte -p$((precisao+2)) ra $num2);;
			rad | "") num="$num2";;
			esac
		else
			zztool erro " zzmat Função Trigonométrica:
	asen: Arco-Seno
	acos: Arco-Cosseno
	atan: Arco-Tangente"
			zztool erro " Retorna o angulo em radianos, graus ou grado."
			zztool erro " Se não for definido retorna em radianos."
			zztool erro " Valores devem estar entre -1 e 1, para arco-seno e arco-cosseno."
			zztool erro " Caso a opção seja '2' retorna o segundo ângulo possível do valor."
			zztool erro " E se for 'r' retorna o ângulo no sentido invertido (replementar)."
			zztool erro " As duas opções poder ser combinadas: r2 ou 2r."
			zztool erro " Uso: zzmat $funcao número [[g|rad|gr] [opção]]"
			return 1
		fi
	;;
	log | ln)
		if test $# -ge "2" && test $# -le "3" && zztestar numero_real $2
		then
			local num1 num2
			num1=$(echo "$2" | tr ',' '.')
			zztestar numero_real "$3" && num2=$(echo "$3" | tr ',' '.')
			if test -n "$num2"
			then
				num="l($num1)/l($num2)"
			elif test "$funcao" = "log"
			then
				num="l($num1)/l(10)"
			else
				num="l($num1)"
			fi
		else
			zztool erro " Se não definir a base no terceiro argumento:"
			zztool erro " zzmat log: Logaritmo base 10"
			zztool erro " zzmat ln: Logaritmo Natural base e"
			zztool erro " Uso: zzmat $funcao numero [base]"
			return 1
		fi
	;;
	raiz)
		if test $# -eq "3" && zztestar numero_real "$3"
		then
			local num1 num2
			case "$2" in
			quadrada)  num1=2;;
			c[úu]bica) num1=3;;
			*)         num1="$2";;
			esac
			num2=$(echo "$3" | tr ',' '.')
			if test $(($num1 % 2)) -eq 0
			then
				if echo "$num2" | grep '^-' > /dev/null
				then
					zztool erro " Não há solução nos números reais para radicando negativo e índice par."
					return 1
				fi
			fi
			if zztestar numero_real $num1
			then
				num=$(awk 'BEGIN {printf "%.'${precisao}'f\n", '$num2'^(1/'$num1')}')
			else
				echo " Uso: zzmat $funcao <quadrada|cubica|numero> numero"
			fi
		else
			zztool erro " zzmat $funcao: Raiz enesima de um número"
			zztool erro " Uso: zzmat $funcao <quadrada|cubica|numero> numero"
			return 1
		fi
	;;
	potencia | elevado | pow)
		if test $# -eq "3" && zztestar numero_real "$2" && zztestar numero_real "$3"
		then
			local num1 num2
			num1=$(echo "$2" | tr ',' '.')
			num2=$(echo "$3" | tr ',' '.')
			if zztestar numero $num2
			then
				num=$(echo "scale=${precisao};${num1}^${num2}" | bc -l | awk '{ printf "%.'${precisao}'f\n", $1 }')
			else
				num=$(awk 'BEGIN {printf "%.'${precisao}'f\n", ('$num1')^('$num2')}')
			fi
		else
			zztool erro " zzmat $funcao: Um número elevado a um potência"
			zztool erro " Uso: zzmat $funcao número potência"
			zztool erro " Uso: zzmat número^potência"
			zztool erro " Ex.: zzmat $funcao 4 3"
			zztool erro " Ex.: zzmat 3^7"
			return 1
		fi
	;;
	area)
		if test $# -ge "2"
		then
			local num1 num2 num3
			case "$2" in
			triangulo)
				if zztestar numero_real $3 && zztestar numero_real $4
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num="${num1}*${num2}/2"
				else
					zztool erro " Uso: zzmat $funcao $2 base altura";return 1
				fi
			;;
			retangulo | losango)
				if zztestar numero_real $3 && zztestar numero_real $4
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num="${num1}*${num2}"
				else
					printf " Uso: zzmat %s %s " $funcao $2 >&2
					test 'retangulo' = "$2" && echo "base altura" >&2 || echo "diagonal_maior diagonal_menor" >&2
					return 1
				fi
			;;
			trapezio)
				if zztestar numero_real $3 && zztestar numero_real $4 && zztestar numero_real $5
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num3=$(echo "$5" | tr ',' '.')
					num="((${num1}+${num2})/2)*${num3}"
				else
					zztool erro " Uso: zzmat $funcao $2 base_maior base_menor altura";return 1
				fi
			;;
			toro)
				if zztestar numero_real $3 && zztestar numero_real $4 && test $(zzmat compara_num $3 $4) != "igual"
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num="4*${pi}^2*${num1}*${num2}"
				else
					zztool erro " Uso: zzmat $funcao $2 raio1 raio2";return 1
				fi
			;;
			tetraedro | cubo | octaedro | dodecaedro | icosaedro | quadrado | circulo | esfera | cuboctaedro | rombicuboctaedro | rombicosidodecaedro | icosidodecaedro)
				if test -n "$3"
				then
					if zztestar numero_real $3
					then
						num1=$(echo "$3" | tr ',' '.')
						case $2 in
						tetraedro)           num="sqrt(3)*${num1}^2";;
						cubo)                num="6*${num1}^2";;
						octaedro)            num="sqrt(3)*2*${num1}^2";;
						dodecaedro)          num="sqrt(25+10*sqrt(5))*3*${num1}^2";;
						icosaedro)           num="sqrt(3)*5*${num1}^2";;
						quadrado)            num="${num1}^2";;
						circulo)             num="$pi*(${num1})^2";;
						esfera)              num="4*$pi*(${num1})^2";;
						cuboctaedro)         num="(6+2*sqrt(3))*${num1}^2";;
						rombicuboctaedro)    num="2*(9+sqrt(3))*${num1}^2";;
						icosidodecaedro)     num="(5*sqrt(3)+3*sqrt(5)*sqrt(5+2*sqrt(5)))*${num1}^2";;
						rombicosidodecaedro) num="(30+sqrt(30*(10+3*sqrt(5)+sqrt(15*(2+2*sqrt(5))))))*${num1}^2";;
						esac
					elif test 'truncado' = $3 && zztestar numero_real $4
					then
						num1=$(echo "$4" | tr ',' '.')
						case $2 in
						tetraedro)       num="7*sqrt(3)*${num1}^2";;
						cubo)            num="2*${num1}^2*(6+6*sqrt(2)+6*sqrt(3))";;
						octaedro)        num="(6+sqrt(3)*12)*${num1}^2";;
						dodecaedro)      num="(sqrt(3)+6*sqrt(5+2*sqrt(5)))*5*${num1}^2";;
						icosaedro)       num="3*(10*sqrt(3)+sqrt(5)*sqrt(5+2*sqrt(5)))*${num1}^2";;
						cuboctaedro)     num="12*(2+sqrt(2)+sqrt(3))*${num1}^2";;
						icosidodecaedro) num="30*(1+sqrt(2*sqrt(4+sqrt(5)+sqrt(15+6*sqrt(6)))))*${num1}^2";;
						esac
					elif test 'snub' = $3 && zztestar numero_real $4
					then
						num1=$(echo "$4" | tr ',' '.')
						case $2 in
						cubo)       num="${num1}^2*(6+8*sqrt(3))";;
						dodecaedro) num="55.286744956*${num1}^2";;
						esac
					else
						zztool erro " Uso: zzmat $funcao $2 lado|raio";return 1
					fi
				else
					zztool erro " Uso: zzmat $funcao $2 lado|raio";return 1
				fi
			;;
			esac
		else
			zztool erro " zzmat $funcao: Cálculo da área de figuras planas e superfícies"
			zztool erro " Uso: zzmat area <triangulo|quadrado|retangulo|losango|trapezio|circulo> numero"
			zztool erro " Uso: zzmat area <esfera|rombicuboctaedro|rombicosidodecaedro> numero"
			zztool erro " Uso: zzmat area <tetraedo|cubo|octaedro|dodecaedro|icosaedro|cuboctaedro|icosidodecaedro> [truncado] numero"
			zztool erro " Uso: zzmat area <cubo|dodecaedro> snub numero"
			zztool erro " Uso: zzmat area toro numero numero"
			return 1
		fi
	;;
	volume)
		if test $# -ge "2"
		then
			local num1 num2 num3
			case "$2" in
			paralelepipedo)
				if zztestar numero_real $3 && zztestar numero_real $4 && zztestar numero_real $5
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num3=$(echo "$5" | tr ',' '.')
					num="${num1}*${num2}*${num3}"
				else
					zztool erro " Uso: zzmat $funcao $2 comprimento largura altura";return 1
				fi
			;;
			cilindro)
				if zztestar numero_real $3 && zztestar numero_real $4
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num="($pi*(${num1})^2)*${num2}"
				else
					zztool erro " Uso: zzmat $funcao $2 raio altura";return 1
				fi
			;;
			cone)
				if zztestar numero_real $3 && zztestar numero_real $4
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num="($pi*(${num1})^2)*${num2}/3"
				else
					zztool erro " Uso: zzmat $funcao $2 raio altura";return 1
				fi
			;;
			prisma)
				if zztestar numero_real $3 && zztestar numero_real $4
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num="${num1}*${num2}"
				else
					zztool erro " Uso: zzmat $funcao $2 area_base altura";return 1
				fi
			;;
			piramide)
				if zztestar numero_real $3 && zztestar numero_real $4
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					num="${num1}*${num2}/3"
				else
					zztool erro " Uso: zzmat $funcao $2 area_base altura";return 1
				fi
			;;
			toro)
				local num_maior num_menor
				if zztestar numero_real $3 && zztestar numero_real $4 && test $(zzmat compara_num $3 $4) != "igual"
				then
					num1=$(echo "$3" | tr ',' '.')
					num2=$(echo "$4" | tr ',' '.')
					test $num1 -gt $num2 && num_maior=$num1 || num_maior=$num2
					test $num1 -lt $num2 && num_menor=$num1 || num_menor=$num2
					num="2*${pi}^2*${num_menor}^2*${num_maior}"
				else
					zztool erro " Uso: zzmat $funcao $2 raio1 raio2";return 1
				fi
			;;
			tetraedro | cubo | octaedro | dodecaedro | icosaedro | esfera | cuboctaedro | rombicuboctaedro | rombicosidodecaedro | icosidodecaedro)
				if test -n "$3"
				then
					if zztestar numero_real $3
					then
						num1=$(echo "$3" | tr ',' '.')
						case $2 in
						tetraedro)           num="sqrt(2)/12*${num1}^3";;
						cubo)                num="${num1}^3";;
						octaedro)            num="sqrt(2)/3*${num1}^3";;
						dodecaedro)          num="(15+7*sqrt(5))*${num1}^3/4";;
						icosaedro)           num="(3+sqrt(5))*${num1}^3*5/12";;
						esfera)              num="$pi*(${num1})^3*4/3";;
						cuboctaedro)         num="5/3*sqrt(2)*${num1}^3";;
						rombicuboctaedro)    num="(2*(6+5*sqrt(2))*${num1}^3)/3";;
						icosidodecaedro)     num="((45+17*sqrt(5))*${num1}^3)/6";;
						rombicosidodecaedro) num="(60+29*sqrt(5))/3*${num1}^3";;
						esac
					elif test 'truncado' = $3 && zztestar numero_real $4
					then
						num1=$(echo "$4" | tr ',' '.')
						case $2 in
						tetraedro)       num="23*sqrt(2)/12*${num1}^3";;
						cubo)            num="(7*${num1}^3*(3+2*sqrt(2)))/3";;
						octaedro)        num="8*sqrt(2)*${num1}^3";;
						dodecaedro)      num="5*(99+47*sqrt(5))/12*${num1}^3";;
						icosaedro)       num="(125+43*sqrt(5))*${num1}^3*1/4";;
						cuboctaedro)     num="(22+14*sqrt(2))*${num1}^3";;
						icosidodecaedro) num="(90+50*sqrt(5))*${num1}^3";;
						esac
					elif test 'snub' = $3 && zztestar numero_real $4
					then
						num1=$(echo "$4" | tr ',' '.')
						case $2 in
						cubo)       num="7.8894774*${num1}^3";;
						dodecaedro) num="37.61664996*${num1}^3";;
						esac
					else
						zztool erro " Uso: zzmat $funcao $2 lado|raio";return 1
					fi
				else
					zztool erro " Uso: zzmat $funcao $2 lado|raio";return 1
				fi
			;;
			esac
		else
			zztool erro " zzmat $funcao: Cálculo de volume de figuras geométricas"
			zztool erro " Uso: zzmat volume <paralelepipedo|cilindro|esfera|cone|prisma|piramide|rombicuboctaedro|rombicosidodecaedro> numero"
			zztool erro " Uso: zzmat volume <tetraedo|cubo|octaedro|dodecaedro|icosaedro|cuboctaedro|icosidodecaedro> [truncado] numero"
			zztool erro " Uso: zzmat volume <cubo|dodecaedro> snub numero"
			zztool erro " Uso: zzmat volume toro numero numero"
			return 1
		fi
	;;
	mmc | mdc)
		if test $# -ge "3"
		then
			local num_maior num_menor resto mdc mmc num2
			local num1=$2
			shift
			shift
			for num2 in $*
			do
				if zztestar numero $num1 && zztestar numero $num2
				then
					test "$num1" -gt "$num2" && num_maior=$num1 || num_maior=$num2
					test "$num1" -lt "$num2" && num_menor=$num1 || num_menor=$num2

					while test "$num_menor" -ne "0"
					do
						resto=$((${num_maior}%${num_menor}))
						num_maior=$num_menor
						num_menor=$resto
					done

					mdc=$num_maior
					mmc=$((${num1}*${num2}/${mdc}))
				fi
				shift
				test "$funcao" = "mdc" && num1="$mdc" || num1="$mmc"
			done

			case $funcao in
			mmc) echo "$mmc";;
			mdc) echo "$mdc";;
			esac
		else
			zztool erro " zzmat mmc: Menor Múltiplo Comum"
			zztool erro " zzmat mdc: Maior Divisor Comum"
			zztool erro " Uso: zzmat $funcao numero numero ..."
			return 1
		fi
	;;
	somatoria | produtoria)
		#colocar x como a variavel a ser substituida
		if test $# -eq "4"
		then
			zzmat $funcao $2 $3 1 $4
		elif test $# -eq "5" && zztestar numero_real $2 && zztestar numero_real $3 && zztestar numero_real $4 && zztool grep_var "x" $5
		then
			local equacao numero operacao sequencia num1 num2
			equacao=$(echo "$5" | sed 's/\[/(/g;s/\]/)/g')
			test "$funcao" = "somatoria" && operacao='+' || operacao='*'
			if test $(zzmat compara_num $2 $3) = 'maior'
			then
				num1=$2; num2=$3
			else
				num1=$3; num2=$2
			fi
			sequencia=$(zzmat pa $num2 $4 $(zzcalcula "(($num1 - $num2)/$4)+1" | zzmat int) | tr ' ' '\n')
			num=$(for numero in $sequencia
			do
				echo "($equacao)" | sed "s/^[x]/($numero)/;s/\([(+-]\)x/\1($numero)/g;s/\([0-9]\)x/\1\*($numero)/g;s/x/$numero/g"
			done | paste -s -d"$operacao" -)
		else
			zztool erro " zzmat $funcao: Soma ou Produto de expressão"
			zztool erro " Uso: zzmat $funcao limite_inferior limite_superior equacao"
			zztool erro " Uso: zzmat $funcao limite_inferior limite_superior razao equacao"
			zztool erro " Usar 'x' como variável na equação"
			zztool erro " Usar '[' e ']' respectivamente no lugar de '(' e ')', ou proteger"
			zztool erro " a fórmula com aspas duplas(\") ou simples(')"
			return 1
		fi
	;;
	media | soma | produto)
		if test $# -ge "2"
		then
			local soma=0
			local qtde=0
			local produto=1
			local peso=1
			local valor
			shift
			while test $# -ne "0"
			do
				if zztool grep_var "[" "$1" && zztool grep_var "]" "$1"
				then
					valor=$(echo "$1" | sed 's/\([0-9]\{1,\}\)\[.*/\1/' | tr ',' '.')
					peso=$(echo "$1" | sed 's/.*\[//;s/\]//')
					if zztestar numero_real "$valor" && zztestar numero "$peso"
					then
						if test $funcao = 'produto'
						then
							produto=$(echo "$produto*(${valor}^${peso})" | bc -l)
						else
							soma=$(echo "$soma+($valor*$peso)" | bc -l)
							qtde=$(($qtde+$peso))
						fi
					fi
				elif zztestar numero_real "$1"
				then
					if test $funcao = 'produto'
					then
						produto=$(echo "($produto) * ($1)" | tr ',' '.' | bc -l)
					else
						soma=$(echo "($soma) + ($1)" | tr ',' '.' | bc -l)
						qtde=$(($qtde+1))
					fi
				else
					zztool -e uso mat; return 1;
				fi
				shift
			done

			case "$funcao" in
			media)   num="${soma}/${qtde}";;
			soma)    num="${soma}";;
			produto) num="${produto}";;
			esac
		else
			zztool erro " zzmat $funcao:Soma, Produto ou Média Aritimética e Ponderada"
			zztool erro " Uso: zzmat $funcao numero[[peso]] [numero[peso]] ..."
			zztool erro " Usar o peso entre '[' e ']', justaposto ao número."
			return 1
		fi
	;;
	fat)
		if test $# -eq "2" -o $# -eq "3" && zztestar numero "$2" && test "$2" -ge "1"
		then
			local num1 num2
			if test 's' = "$3"
			then
				num1=$(zzseq $2)
			else
				num1="$2"
			fi
			for num2 in $(echo "$num1")
			do
				echo "define fat(x) { if (x <= 1) return (1); return (fat(x-1) * x); }; fat($num2)" |
				bc |
				tr -d '\\\n' |
				zztool nl_eof
			done |
			tr '\n' ' ' |
			zztrim |
			zztool nl_eof
		else
			zztool erro " zzmat $funcao: Resultado do produto de 1 ao numero atual (fatorial)"
			zztool erro " Com o argumento 's' imprime a sequência até a posição."
			zztool erro " Uso: zzmat $funcao numero [s]"
			zztool erro " Uso: zzmat numero! [s]"
			zztool erro " Ex.: zzmat $funcao 4"
			zztool erro "      zzmat 5!"
			return 1
		fi
	;;
	arranjo | combinacao | arranjo_r | combinacao_r)
		if test $# -eq "3" && zztestar numero "$2" && zztestar numero "$3" && test "$2" -ge "$3" && test "$3" -ge "1"
		then
			local n p dnp
			n=$(zzmat fat $2)
			p=$(zzmat fat $3)
			dnp=$(zzmat fat $(($2-$3)))
			case "$funcao" in
			arranjo)    test "$2" -gt "$3" && num="${n}/${dnp}" || return 1;;
			arranjo_r)  zzmat elevado "$2" "$3";;
			combinacao) test "$2" -gt "$3" && num="${n}/(${p}*${dnp})" || return 1;;
			combinacao_r)
				if test "$2" -gt "$3"
				then
					n=$(zzmat fat $(($2+$3-1)))
					dnp=$(zzmat fat $(($2-1)))
					num="${n}/(${p}*${dnp})"
				else
					return 1
				fi
			;;
			esac
		else
			zztool erro " zzmat arranjo: n elementos tomados em grupos de p (considera ordem)"
			zztool erro " zzmat arranjo_r: n elementos tomados em grupos de p com repetição (considera ordem)"
			zztool erro " zzmat combinacao: n elementos tomados em grupos de p (desconsidera ordem)"
			zztool erro " zzmat combinacao_r: n elementos tomados em grupos de p com repetição (desconsidera ordem)"
			zztool erro " Uso: zzmat $funcao total_numero quantidade_grupo"
			return 1
		fi
	;;
	newton | binomio_newton)
		if test "$#" -ge "2"
		then
			local num1 num2 grau sinal parcela coeficiente
			num1="a"
			num2="b"
			sinal="+"
			zztestar numero "$2" && grau="$2"
			if test -n "$3"
			then
				if test '+' = "$3" -o '-' = "$3"
				then
					sinal="$3"
					test -n "$4" && num1="$4"
					test -n "$5" && num2="$5"
				else
					test -n "$3" && num1="$3"
					test -n "$4" && num2="$4"
				fi
			fi
			echo "($num1)^$grau"
			for parcela in $(zzseq $((grau-1)))
			do
				coeficiente=$(zzmat combinacao $grau $parcela)
				test "$sinal" = "-" -a $((parcela%2)) -eq 1 && printf "%s" "- " || printf "%s" "+ "
				printf "%s * " "$coeficiente"
				echo "($num1)^$(($grau-$parcela)) * ($num2)^$parcela" | sed 's/\^1\([^0-9]\)/\1/g;s/\^1$//'
			done
			test "$sinal" = "-" -a $((grau%2)) -eq 1 && printf "%s" "- " || printf "%s" "+ "
			echo "($num2)^$grau"
		else
			echo " zzmat $funcao: Exibe o desdobramento do binônimo de Newton."
			echo " Exemplo no grau 3: (a + b)^3 = a^3 + 2a^2b + 2ab^2 + b^3"
			echo " Se nenhum sinal for especificado será assumido '+'"
			echo " Se não declarar variáveis serão assumidos 'a' e 'b'"
			echo " Uso: zzmat $funcao grau [+|-] [variavel(a) [variavel(b)]]"
		fi
	;;
	pa | pa2 | pg)
		if test $# -eq "4" && zztestar numero_real "$2" && zztestar numero_real "$3" && zztestar numero "$4"
		then
			local num_inicial razao passo valor
			num_inicial=$(echo "$2" | tr ',' '.')
			razao=$(echo "$3" | tr ',' '.')
			passo=0
			valor=$num_inicial
			while (test $passo -lt $4)
			do
				if test "$funcao" = "pa"
				then
					valor=$(echo "$num_inicial + ($razao * $passo)" | bc -l |
					awk '{printf "%.'${precisao}'f\n", $1}')
				elif test "$funcao" = "pa2"
				then
					valor=$(echo "$valor + ($razao * $passo)" | bc -l |
					awk '{printf "%.'${precisao}'f\n", $1}')
				else
					valor=$(echo "$num_inicial * $razao^$passo" | bc -l |
					awk '{printf "%.'${precisao}'f\n", $1}')
				fi
				valor=$(echo "$valor" | zzmat -p${precisao} sem_zeros)
				test $passo -lt $(($4 - 1)) && printf "%s " "$valor" || printf "%s" "$valor"
				passo=$(($passo+1))
			done
			echo
		else
			zztool erro " zzmat pa:  Progressão Aritmética"
			zztool erro " zzmat pa2: Progressão Aritmética de Segunda Ordem"
			zztool erro " zzmat pg:  Progressão Geométrica"
			zztool erro " Uso: zzmat $funcao inicial razao quantidade_elementos"
			return 1
		fi
	;;
	fibonacci | fib | lucas)
	# Sequência ou número de fibonacci
		if zztestar numero "$2"
		then
			awk 'BEGIN {
					seq = ( "'$3'" == "s" ? 1 : 0 )
					num1 = ( "'$funcao'" == "lucas" ? 2 : 0 )
					num2 = 1
					for ( i = 0; i < '$2' + seq; i++ ) {
						if ( seq == 1 ) { printf "%s ", num1 }
						num3 = num1 + num2
						num1 = num2
						num2 = num3
					}
					if ( seq != 1 ) { printf "%s ", num1 }
				}' |
				zztrim -r |
				zztool nl_eof
		else
			echo " Número de Fibonacci ou Lucas na posição especificada."
			echo " Com o argumento 's' imprime a sequência até a posição."
			echo " Uso: zzmat $funcao <número> [s]"
		fi
	;;
	tribonacci | trib)
	# Sequência ou número Tribonacci
		if zztestar numero "$2"
		then
			awk 'BEGIN {
					seq = ( "'$3'" == "s" ? 1 : 0 )
					num1 = 0
					num2 = 0
					num3 = 1
					for ( i = 0; i < '$2' + seq; i++ ) {
						if ( seq == 1 ) { printf "%s ", num1 }
						num4 = num1 + num2 + num3
						num1 = num2
						num2 = num3
						num3 = num4
					}
					if ( seq != 1 ) { printf "%s ", num1 }
				}' |
				zztrim -r |
				zztool nl_eof
		else
			echo " Número de Tribonacci na posição especificada."
			echo " Com o argumento 's' imprime a sequência até a posição."
			echo " Uso: zzmat $funcao <número> [s]"
		fi
	;;
	recaman)
	# Sequência ou número Recamán
		if zztestar numero "$2"
		then
			awk 'BEGIN {
					seq = ( "'$3'" == "s" ? 1 : 0 )
					a[0]=0; b[0]=0
					for ( i = 1; i <= '$2'; i++ ) {
						num=a[i-1]
						a[i] = ((num > i && ! ((num - i) in b)) ? num - i : num + i)
						b[a[i]]=i
					}
					if ( seq ) { for (i=0; i<length(a); i++) printf "%d ", a[i] }
					else { print a[length(a)-1] }
				}' |
				zztrim -r |
				zztool nl_eof
		else
			echo " Número de Recamán na posição especificada."
			echo " Com o argumento 's' imprime a sequência até a posição."
			echo " Uso: zzmat $funcao <número> [s]"
		fi
	;;
	mersenne)
	# Sequência ou número de Mersenne
		if zztestar numero "$2"
		then
			zzseq -f '2^%d-1\n' 0 $2 |
			bc |
			awk '{ if ($0 ~ /\\$/) { sub(/\\/,""); printf $0 } else { print } }' |
			if test 's' = "$3"
			then
				zztool lines2list | zztool nl_eof
			else
				sed -n '$p'
			fi
		else
				echo " Número de Mersenne na posição especificada."
				echo " Com o argumento 's' imprime a sequência até a posição."
				echo " Uso: zzmat $funcao <número> [s]"
		fi
	;;
	collatz)
	# Sequência de Collatz
	if zztestar numero "$2"
	then
		awk '
				function collatz(num) {
					printf num " "
					if (num>1) {
						if (num%2==0) { collatz(num/2) }
						else { collatz(3*num+1) }
					}
				}
				BEGIN { collatz('$2')}
			' |
			zztrim |
			zztool nl_eof
	else
		echo " Sequência de Collatz"
		echo " Uso: zzmat $funcao <número>"
	fi
	;;
	r3)
		shift
		if test -n "$1"
		then
			local num num1 num2 ind
			local num3=0
			local num4=0
			while test -n "$1"
			do
				num="$1"
				ind=1
				zztool grep_var "i" "$1" && ind=0 && num=$(echo "$1" | sed 's/i//')
				if (zztestar numero_real ${num%/*} || test ${num%/*} = 'x') && (zztestar numero_real ${num#*/} || test ${num#*/} = 'x')
				then
					num3=$((num3+1))
					if test $((num3%2)) -eq $ind
					then
						test ${num%/*} != 'x' && num1="$num1 ${num%/*}" || num4=$((num4+1))
						test ${num#*/} != 'x' && num2="$num2 ${num#*/}" || num4=$((num4+1))
					else
						test ${num%/*} != 'x' && num2="$num2 ${num%/*}" || num4=$((num4+1))
						test ${num#*/} != 'x' && num1="$num1 ${num#*/}" || num4=$((num4+1))
					fi
				fi
				shift
			done

			unset num
			if test $num4 -eq 1 && test -n "$num1" && test -n "$num2"
			then
				case $(zzmat compara_num $(echo "$num1" | awk '{print NF}') $(echo "$num2" | awk '{print NF}')) in
				maior)
					num=$(echo $(zzmat produto $num1)"/"$(zzmat produto $num2))
				;;
				menor)
					num=$(echo $(zzmat produto $num2)"/"$(zzmat produto $num1))
				;;
				*)
					zzmat $funcao
				;;
				esac
			else
				zzmat $funcao
			fi
		else
			echo " Calcula o valor de 'x', usando a regra de 3 simples ou composta."
			echo " Se alguma das frações tiver a letra i justaposta, é considerada inversamente proporcional."
			echo " Obs.: o i pode ser antes ou depois, mas não pode haver espaço em relação a fração."
			echo "       no local do valor a ser encontrado, digite apenas 'x', e somente uma vez."
			echo " Uso: zzmat $funcao <fração1>[i] <fração2>[i] [<fração3>[i] ...]"
		fi
	;;
	eq2g)
	#Equação do Segundo Grau: Raizes e Vértice
		if test $# = "4" && zztestar numero_real $2 && zztestar numero_real $3 && zztestar numero_real $4
		then
			local delta num_raiz vert_x vert_y raiz1 raiz2
			delta=$(echo "$2 $3 $4" | tr ',' '.' | awk '{valor=$2^2-(4*$1*$3); print valor}')
			num_raiz=$(awk 'BEGIN { if ('$delta' > 0)  {print "2"}
									if ('$delta' == 0) {print "1"}
									if ('$delta' < 0)  {print "0"}}')

			vert_x=$(echo "$2 $3" | tr ',' '.' |
			awk '{valor=((-1 * $2)/(2 * $1)); printf "%.'${precisao}'f\n", valor}' |
			zzmat -p${precisao} sem_zeros )

			vert_y=$(echo "$2 $delta" | tr ',' '.' |
			awk '{valor=((-1 * $2)/(4 * $1)); printf "%.'${precisao}'f\n", valor}' |
			zzmat -p${precisao} sem_zeros )

			case $num_raiz in
			0) raiz1="Sem raiz";;
			1) raiz1=$vert_x;;
			2)
				raiz1=$(echo "$2 $3 $delta" | tr ',' '.' |
				awk '{valor=((-1 * $2)-sqrt($3))/(2 * $1); printf "%.'${precisao}'f\n", valor}' |
				zzmat -p${precisao} sem_zeros )

				raiz2=$(echo "$2 $3 $delta" | tr ',' '.' |
				awk '{valor=((-1 * $2)+sqrt($3))/(2 * $1); printf "%.'${precisao}'f\n", valor}' |
				zzmat -p${precisao} sem_zeros )
			;;
			esac
			test "$num_raiz" = "2" && printf "%b\n" "X1: ${raiz1}\nX2: ${raiz2}" || echo "X: $raiz1"
			echo "Vertice: (${vert_x}, ${vert_y})"
		else
			zztool erro " zzmat $funcao: Equação do Segundo Grau (Raízes e Vértice)"
			zztool erro " Uso: zzmat $funcao A B C"
			return 1
		fi
	;;
	d2p)
		if test $# = "3" && zztool grep_var "," "$2" && zztool grep_var "," "$3"
		then
			local x1 y1 z1 x2 y2 z2 a b
			x1=$(echo "$2" | cut -f1 -d,)
			y1=$(echo "$2" | cut -f2 -d,)
			z1=$(echo "$2" | cut -f3 -d,)
			x2=$(echo "$3" | cut -f1 -d,)
			y2=$(echo "$3" | cut -f2 -d,)
			z2=$(echo "$3" | cut -f3 -d,)
			if zztestar numero_real $x1 && zztestar numero_real $y1 && zztestar numero_real $x2 && zztestar numero_real $y2
			then
				a=$(echo "(($y1)-($y2))^2" | bc -l)
				b=$(echo "(($x1)-($x2))^2" | bc -l)
				if zztestar numero_real $z1 && zztestar numero_real $z2
				then
					num="sqrt((($z1)-($z2))^2+$a+$b)"
				else
					num="sqrt($a+$b)"
				fi
			else
				zztool erro " Uso: zzmat $funcao ponto(a,b) ponto(x,y)";return 1
			fi
		else
			zztool erro " zzmat $funcao: Distância entre 2 pontos"
			zztool erro " Uso: zzmat $funcao ponto(a,b) ponto(x,y)"
			return 1
		fi
	;;
	vetor)
		if test $# -ge "3"
		then
			local valor ang teta fi oper tipo num1 saida
			local x1=0
			local y1=0
			local z1=0
			shift

			test '-e' = "$1" -o '-c' = "$1" && tipo="$1" || tipo="-e"
			oper="+"
			saida=$(echo "$*" | awk '{print $NF}')

			while (test $# -ge "1")
			do
				valor=$(echo "$1" | cut -f1 -d,)
				zztool grep_var "," $1 && teta=$(echo "$1" | cut -f2 -d,)
				zztool grep_var "," $1 && fi=$(echo "$1" | cut -f3 -d,)

				if test -n "$fi" && zztestar numero_real $valor
				then
					num1=$(echo "$fi" | sed 's/g$//; s/gr$//; s/rad$//')
					ang=$(echo "$fi" | tr -d -c '[grad]')
					echo "$fi" | grep -E '(g|rad|gr)$' >/dev/null
					if test "$?" -eq "0" && zztestar numero_real $num1
					then
						case $ang in
						g)   fi=$(zzconverte -p$((precisao+2)) gr $num1);;
						gr)  fi=$(zzconverte -p$((precisao+2)) ar $num1);;
						rad) fi=$num1;;
						esac
						z1=$(echo "$z1 $oper $(zzmat cos ${fi}rad) * $valor" | bc -l)
					elif zztestar numero_real $num1
					then
						z1="$num1"
					fi
				fi

				if test -n "$teta" && zztestar numero_real $valor
				then
					num1=$(echo "$teta" | sed 's/g$//; s/gr$//; s/rad$//')
					ang=$(echo "$teta" | tr -d -c '[grad]')
					echo "$teta" | grep -E '(g|rad|gr)$' >/dev/null
					if test "$?" -eq "0" && zztestar numero_real $num1
					then
						case $ang in
						g)   teta=$(zzconverte -p$((precisao+2)) gr $num1);;
						gr)  teta=$(zzconverte -p$((precisao+2)) ar $num1);;
						rad) teta=$num1;;
						esac
					else
						unset teta
					fi
				fi

				if zztestar numero_real $valor
				then
					test -n "$fi" && num1=$(echo "$(zzmat sen ${fi}rad)*$valor" | bc -l) ||
						num1=$valor
					test -n "$teta" && x1=$(echo "$x1 $oper $(zzmat cos ${teta}rad) * $num1" | bc -l) ||
						x1=$(echo "($x1) $oper ($num1)" | bc -l)
					test -n "$teta" && y1=$(echo "$y1 $oper $(zzmat sen ${teta}rad) * $num1" | bc -l)
				fi
				shift
			done

			valor=$(echo "sqrt(${x1}^2+${y1}^2+${z1}^2)" | bc -l)
			teta=$(zzmat asen $(echo "${y1}/sqrt(${x1}^2+${y1}^2)" | bc -l))
			fi=$(zzmat acos $(echo "${z1}/${valor}" | bc -l))

			case $saida in
			g)
				teta=$(zzconverte -p$((precisao+2)) rg $teta)
				fi=$(zzconverte -p$((precisao+2)) rg $fi)
			;;
			gr)
				teta=$(zzconverte -p$((precisao+2)) ra $teta)
				fi=$(zzconverte -p$((precisao+2)) ra $fi)
			;;
			*) saida="rad";;
			esac

			teta=$(awk 'BEGIN {printf "%.'${precisao}'f\n", '$teta'}' | zzmat -p${precisao} sem_zeros )
			fi=$(awk 'BEGIN {printf "%.'${precisao}'f\n", '$fi'}' | zzmat -p${precisao} sem_zeros )

			if test '-c' = "$tipo"
			then
				valor=$(echo "sqrt(${valor}^2-$z1^2)" | bc -l |
					awk '{printf "%.'${precisao}'f\n", $1}' | zzmat -p${precisao} sem_zeros )
				echo "${valor}, ${teta}${saida}, ${z1}"
			else
				valor=$(echo "$valor" | bc -l |
					awk '{printf "%.'${precisao}'f\n", $1}' | zzmat -p${precisao} sem_zeros )
				echo "${valor}, ${teta}${saida}, ${fi}${saida}"
			fi
		else
			zztool erro " zzmat $funcao: Operação entre vetores"
			zztool erro " Tipo de saída podem ser: padrão (-e)"
			zztool erro "  -e: vetor em coordenadas esférica: valor[,teta(g|rad|gr),fi(g|rad|gr)];"
			zztool erro "  -c: vetor em coordenada cilindrica: raio[,teta(g|rad|gr),altura]."
			zztool erro " Os angulos teta e fi tem sufixos g(graus), rad(radianos) ou gr(grados)."
			zztool erro " Os argumentos de entrada seguem o mesmo padrão do tipo de saída."
			zztool erro " E os tipos podem ser misturados em cada argumento."
			zztool erro " Unidade angular é o angulo de saida usado para o vetor resultante,"
			zztool erro " e pode ser escolhida entre g(graus), rad(radianos) ou gr(grados)."
			zztool erro " Não use separador de milhar. Use o ponto(.) como separador decimal."
			zztool erro " Uso: zzmat $funcao [tipo saida] vetor [vetor2] ... [unidade angular]"
			return 1
		fi
	;;
	egr | err)
	#Equação Geral da Reta
	#ax + by + c = 0
	#y1 – y2 = a
	#x2 – x1 = b
	#x1y2 – x2y1 = c
		if test $# = "3" && zztool grep_var "," "$2" && zztool grep_var "," "$3"
		then
			local x1 y1 x2 y2 a b c redutor m
			x1=$(echo "$2" | cut -f1 -d,)
			y1=$(echo "$2" | cut -f2 -d,)
			x2=$(echo "$3" | cut -f1 -d,)
			y2=$(echo "$3" | cut -f2 -d,)
			if zztestar numero_real $x1 && zztestar numero_real $y1 && zztestar numero_real $x2 && zztestar numero_real $y2
			then
				a=$(awk 'BEGIN {valor=('$y1')-('$y2'); printf "%.'${precisao}'f\n", valor}' | zzmat -p${precisao} sem_zeros)
				b=$(awk 'BEGIN {valor=('$x2')-('$x1');  printf "%+.'${precisao}'f\n", valor}' | zzmat -p${precisao} sem_zeros)
				c=$(zzmat det $x1 $y1 $x2 $y2 | awk '{printf "%+.'${precisao}'f\n", $1}' | zzmat -p${precisao} sem_zeros)
				m=$(awk 'BEGIN {valor=(('$y2'-'$y1')/('$x2'-'$x1')); printf "%.'${precisao}'f\n", valor}' | zzmat -p${precisao} sem_zeros)
				if zztestar numero_sinal $a && zztestar numero_sinal $b && zztestar numero_sinal $c
				then
					redutor=$(zzmat mdc $(zzmat abs $a) $(zzmat abs $b) $(zzmat abs $c))
					a=$(awk 'BEGIN {valor=('$a')/('$redutor'); print valor}')
					b=$(awk 'BEGIN {valor=('$b')/('$redutor');  print (valor<0?"":"+") valor}')
					c=$(awk 'BEGIN {valor=('$c')/('$redutor');  print (valor<0?"":"+") valor}')
				fi

				case "$funcao" in
				egr)
					echo "${a}x${b}y${c}=0" |
					sed 's/\([+-]\)1\([xy]\)/\1\2/g;s/[+]\{0,1\}0[xy]//g;s/+0=0/=0/;s/^+//';;
				err)
					redutor=$(awk 'BEGIN {printf "%+.'${precisao}'f\n", -('$m'*'$x1')+'$y1'}' | zzmat -p${precisao} sem_zeros)
					echo "y=${m}x${redutor}";;
				esac
			else
				zztool erro " Uso: zzmat $funcao ponto(a,b) ponto(x,y)";return 1
			fi
		else
			printf " zzmat %s: " $funcao
			case "$funcao" in
			egr) echo "Equação Geral da Reta.";;
			err) echo "Equação Reduzida da Reta.";;
			esac
			zztool erro " Uso: zzmat $funcao ponto(a,b) ponto(x,y)"
			return 1
		fi
	;;
	egc)
	#Equação Geral da Circunferência: Centro e Raio ou Centro e Ponto
	#x2 + y2 - 2ax - 2by + a2 + b2 - r2 = 0
	#A=-2ax | B=-2by | C=a2+b2-r2
	#r=raio | a=coordenada x do centro | b=coordenada y do centro
		if test $# = "3" && zztool grep_var "," "$2"
		then
			local a b r A B C
			if zztool grep_var "," "$3"
			then
				r=$(zzmat d2p $2 $3)
			elif zztestar numero_real "$3"
			then
				r=$(echo "$3" | tr ',' '.')
			else
				zztool erro " Uso: zzmat $funcao centro(a,b) (numero|ponto(x,y))";return 1
			fi
			a=$(echo "$2" | cut -f1 -d,)
			b=$(echo "$2" | cut -f2 -d,)
			A=$(awk 'BEGIN {valor=-2*('$a'); print (valor<0?"":"+") valor}')
			B=$(awk 'BEGIN {valor=-2*('$b'); print (valor<0?"":"+") valor}')
			C=$(awk 'BEGIN {valor=('$a')^2+('$b')^2-('$r')^2; print (valor<0?"":"+") valor}')
			echo "x^2+y^2${A}x${B}y${C}=0" | sed 's/\([+-]\)1\([xy]\)/\1\2/g;s/[+]0[xy]//g;s/+0=0/=0/'
		else
			zztool erro " zzmat $funcao: Equação Geral da Circunferência (Centro e Raio ou Centro e Ponto)"
			zztool erro " Uso: zzmat $funcao centro(a,b) (numero|ponto(x,y))"
			return 1
		fi
	;;
	egc3p)
	#Equação Geral da Circunferência: 3 Pontos
		if test $# = "4" && zztool grep_var "," "$2" &&	zztool grep_var "," "$3" && zztool grep_var "," "$4"
		then
			local x1 y1 x2 y2 x3 y3 A B C D
			x1=$(echo "$2" | cut -f1 -d,)
			y1=$(echo "$2" | cut -f2 -d,)
			x2=$(echo "$3" | cut -f1 -d,)
			y2=$(echo "$3" | cut -f2 -d,)
			x3=$(echo "$4" | cut -f1 -d,)
			y3=$(echo "$4" | cut -f2 -d,)

			if test $(zzmat det $x1 $y1 1 $x2 $y2 1 $x3 $y3 1) -eq 0
			then
				zztool erro "Pontos formam uma reta."
				return 1
			fi

			if ! zztestar numero_real $x1 || ! zztestar numero_real $x2 || ! zztestar numero_real $x3
			then
				zztool erro " Uso: zzmat $funcao ponto(a,b) ponto(c,d) ponto(x,y)";return 1
			fi

			if ! zztestar numero_real $y1 || ! zztestar numero_real $y2 || ! zztestar numero_real $y3
			then
				zztool erro " Uso: zzmat $funcao ponto(a,b) ponto(c,d) ponto(x,y)";return 1
			fi

			D=$(zzmat det $x1 $y1 1 $x2 $y2 1 $x3 $y3 1)
			A=$(zzmat det -$(echo "$x1^2+$y1^2" | bc) $y1 1 -$(echo "$x2^2+$y2^2" | bc) $y2 1 -$(echo "$x3^2+$y3^2" | bc) $y3 1)
			B=$(zzmat det $x1 -$(echo "$x1^2+$y1^2" | bc) 1 $x2 -$(echo "$x2^2+$y2^2" | bc) 1 $x3 -$(echo "$x3^2+$y3^2" | bc) 1)
			C=$(zzmat det $x1 $y1 -$(echo "$x1^2+$y1^2" | bc) $x2 $y2 -$(echo "$x2^2+$y2^2" | bc) $x3 $y3 -$(echo "$x3^2+$y3^2" | bc))

			A=$(awk 'BEGIN {valor='$A'/'$D';print (valor<0?"":"+") valor}')
			B=$(awk 'BEGIN {valor='$B'/'$D';print (valor<0?"":"+") valor}')
			C=$(awk 'BEGIN {valor='$C'/'$D';print (valor<0?"":"+") valor}')

			x1=$(awk 'BEGIN {valor='$A'/2*-1;print valor}')
			y1=$(awk 'BEGIN {valor='$B'/2*-1;print valor}')

			echo "x^2+y^2${A}x${B}y${C}=0" |
			sed 's/\([+-]\)1\([xy]\)/\1\2/g;s/[+]0[xy]//g;s/+0=0/=0/'
			echo "Centro: (${x1}, ${y1})"
		else
			zztool erro " zzmat $funcao: Equação Geral da Circunferência (3 pontos)"
			zztool erro " Uso: zzmat $funcao ponto(a,b) ponto(c,d) ponto(x,y)"
			return 1
		fi
	;;
	ege)
	#Equação Geral da Esfera: Centro e Raio ou Centro e Ponto
	#x2 + y2 + z2 - 2ax - 2by -2cz + a2 + b2 + c2 - r2 = 0
	#A=-2ax | B=-2by | C=-2cz | D=a2+b2+c2-r2
	#r=raio | a=coordenada x do centro | b=coordenada y do centro | c=coordenada z do centro
		if test $# = "3" && zztool grep_var "," "$2"
		then
			local a b c r A B C D
			if zztool grep_var "," "$3"
			then
				r=$(zzmat d2p $2 $3)
			elif zztestar numero_real "$3"
			then
				r=$(echo "$3" | tr ',' '.')
			else
				zztool erro " Uso: zzmat $funcao centro(a,b,c) (numero|ponto(x,y,z))";return 1
			fi
			a=$(echo "$2" | cut -f1 -d,)
			b=$(echo "$2" | cut -f2 -d,)
			c=$(echo "$2" | cut -f3 -d,)

			if ! zztestar numero_real $a || ! zztestar numero_real $b || ! zztestar numero_real $c
			then
				zztool erro " Uso: zzmat $funcao centro(a,b,c) (numero|ponto(x,y,z))";return 1
			fi
			A=$(awk 'BEGIN {valor=-2*('$a'); print (valor<0?"":"+") valor}')
			B=$(awk 'BEGIN {valor=-2*('$b'); print (valor<0?"":"+") valor}')
			C=$(awk 'BEGIN {valor=-2*('$c'); print (valor<0?"":"+") valor}')
			D=$(awk 'BEGIN {valor='$a'^2+'$b'^2+'$c'^2-'$r'^2;print (valor<0?"":"+") valor}')
			echo "x^2+y^2+z^2${A}x${B}y${C}z${D}=0" |
			sed 's/\([+-]\)1\([xyz]\)/\1\2/g;s/[+]0[xyz]//g;s/+0=0/=0/'
		else
			zztool erro " zzmat $funcao: Equação Geral da Esfera (Centro e Raio ou Centro e Ponto)"
			zztool erro " Uso: zzmat $funcao centro(a,b,c) (numero|ponto(x,y,z))"
			return 1
		fi
	;;
	aleatorio | random)
		#Gera um numero aleatorio (randomico)
		local min=0
		local max=1
		local qtde=1
		local n_temp

		if test '-h' = "$2"
		then
			echo " zzmat $funcao: Gera um número aleatório."
			echo " Sem argumentos gera números entre 0 e 1."
			echo " Com 1 argumento numérico este fica como limite superior."
			echo " Com 2 argumentos numéricos estabelecem os limites inferior e superior, respectivamente."
			echo " Com 3 argumentos numéricos, o último é a quantidade de número aleatórios gerados."
			echo " Usa padrão de 6 casas decimais. Use -p0 logo após zzmat para números inteiros."
			echo " Uso: zzmat $funcao [[minimo] maximo] [quantidade]"
			return
		fi

		if zztestar numero_real $3
		then
			max=$(echo "$3" | tr ',' '.')
			if zztestar numero_real $2;then min=$(echo "$2" | tr ',' '.');fi
		elif zztestar numero_real $2
		then
			max=$(echo "$2" | tr ',' '.')
		fi

		if test $(zzmat compara_num $max $min) = "menor"
		then
			n_temp=$max
			max=$min
			min=$n_temp
			unset n_temp
		fi

		if test -n "$4" && zztestar numero $4;then qtde=$4;fi

		case "$funcao" in
		aleatorio)
			awk 'BEGIN {srand();for(i=1;i<='$qtde';i++) { printf "%.'${precisao}'f\n", sprintf("%.'${precisao}'f\n",'$min'+rand()*('$max'-'$min'))}}' |
			zzmat -p${precisao} sem_zeros
			sleep 1
		;;
		random)
			n_temp=1
			while test $n_temp -le $qtde
			do
				zzaleatorio | awk '{ printf "%.'${precisao}'f\n", sprintf("%.'${precisao}'f\n",'$min'+($1/32767)*('$max'-'$min'))}' |
				zzmat -p${precisao} sem_zeros
				n_temp=$((n_temp + 1))
			done
		;;
		esac
	;;
	det)
		# Determinante de matriz (2x2 ou 3x3)
		if test $# -ge "5" && test $# -le "10"
		then
			local num
			shift
			for num in $*
			do
				if ! zztestar numero_real "$num"
				then
					zztool erro " Uso: zzmat $funcao numero1 numero2 numero3 numero4 [numero5 numero6 numero7 numero8 numero9]"
					return 1
				fi
			done
			case $# in
			4) num=$(echo "($1*$4)-($2*$3)" | tr ',' '.');;
			9) num=$(echo "(($1*$5*$9)+($7*$2*$6)+($4*$8*$3)-($7*$5*$3)-($4*$2*$9)-($1*$8*$6))" | tr ',' '.');;
			*)   zztool erro " Uso: zzmat $funcao numero1 numero2 numero3 numero4 [numero5 numero6 numero7 numero8 numero9]"; return 1;;
			esac
		else
			echo " zzmat $funcao: Calcula o valor da determinante de uma matriz 2x2 ou 3x3."
			echo " Uso: zzmat $funcao numero1 numero2 numero3 numero4 [numero5 numero6 numero7 numero8 numero9]"
			echo " Ex:  zzmat det 1 3 2 4"
		fi
	;;
	conf_eq)
		# Confere equação
		if test $# -ge "2"
		then
			equacao=$(echo "$2" | sed 's/\[/(/g;s/\]/)/g')
			local x y z eq
			shift
			shift
			while (test $# -ge "1")
			do
				x=$(echo "$1" | cut -f1 -d,)
				zztool grep_var "," $1 && y=$(echo "$1" | cut -f2 -d,)
				zztool grep_var "," $1 && z=$(echo "$1" | cut -f3 -d,)
				eq=$(echo $equacao | sed "s/^[x]/$x/;s/\([(+-]\)x/\1($x)/g;s/\([0-9]\)x/\1\*($x)/g;s/x/$x/g" |
					sed "s/^[y]/$y/;s/\([(+-]\)y/\1($y)/g;s/\([0-9]\)y/\1\*($y)/g;s/y/$y/g" |
					sed "s/^[z]/$z/;s/\([(+-]\)z/\1($z)/g;s/\([0-9]\)z/\1\*($z)/g;s/z/$z/g")
				echo "$eq" | bc -l
				unset x y z eq
				shift
			done
		else
			zztool erro " zzmat $funcao: Confere ou resolve equação."
			zztool erro " As variáveis a serem consideradas são x, y ou z nas fórmulas."
			zztool erro " As variáveis são justapostas em cada argumento separados por vírgula."
			zztool erro " Cada argumento adicional é um novo conjunto de variáveis na fórmula."
			zztool erro " Usar '[' e ']' respectivamente no lugar de '(' e ')', ou proteger"
			zztool erro " a fórmula com aspas duplas(\") ou simples(')"
			zztool erro " Potenciação é representado com o uso de '^', ex: 3^2."
			zztool erro " Não use separador de milhar. Use o ponto(.) como separador decimal."
			zztool erro " Uso: zzmat $funcao equacao numero|ponto(x,y[,z])"
			zztool erro " Ex:  zzmat conf_eq x^2+3*[y-1]-2z+5 7,6.8,9 3,2,5.1"
			return 1
		fi
	;;
	*)
	zzmat -h
	;;
	esac

	if test "$?" -ne "0"
	then
		return 1
	elif test -n "$num"
	then
		echo "$num" | bc -l | awk '{printf "%.'${precisao}'f\n", $1}' | zzmat -p${precisao} sem_zeros
	fi
}
