package decimal128_test

import (
	"fmt"
	"slices"

	"github.com/woodsbury/decimal128"
)

func ExampleAbs() {
	x := decimal128.New(3, 0)
	y := decimal128.New(-3, 0)
	inf := decimal128.Inf(-1)
	nan := decimal128.NaN()
	fmt.Printf("Abs(%g) = %g\n", x, decimal128.Abs(x))
	fmt.Printf("Abs(%g) = %g\n", y, decimal128.Abs(y))
	fmt.Printf("Abs(%g) = %g\n", inf, decimal128.Abs(inf))
	fmt.Printf("Abs(%g) = %g\n", nan, decimal128.Abs(nan))
	// Output:
	// Abs(3) = 3
	// Abs(-3) = 3
	// Abs(-Inf) = +Inf
	// Abs(NaN) = NaN
}

func ExampleCeil() {
	x := decimal128.New(-123, -2)
	y := decimal128.New(789, -2)
	fmt.Println(decimal128.Ceil(x))
	fmt.Println(decimal128.Ceil(y))
	// Output:
	// -1
	// 8
}

func ExampleCompare() {
	s := []decimal128.Decimal{
		decimal128.New(3, 0),
		decimal128.New(1, 0),
		decimal128.NaN(),
		decimal128.Inf(1),
		decimal128.New(2, 0),
		decimal128.Inf(-1),
	}

	fmt.Println(s)
	fmt.Println(slices.MinFunc(s, decimal128.Compare))
	fmt.Println(slices.MaxFunc(s, decimal128.Compare))
	slices.SortFunc(s, decimal128.Compare)
	fmt.Println(s)
	// Output:
	// [3 1 NaN +Inf 2 -Inf]
	// NaN
	// +Inf
	// [NaN -Inf 1 2 3 +Inf]
}

func ExampleFloor() {
	x := decimal128.New(-123, -2)
	y := decimal128.New(789, -2)
	fmt.Println(decimal128.Floor(x))
	fmt.Println(decimal128.Floor(y))
	// Output:
	// -2
	// 7
}

func ExampleFrexp() {
	x := decimal128.New(123, -2)
	frac, exp := decimal128.Frexp(x)
	fmt.Println(frac, exp)
	fmt.Println(decimal128.Ldexp(frac, exp))
	// Output:
	// 0.123 1
	// 1.23
}

func ExampleNew() {
	fmt.Println(decimal128.New(3, -2))
	fmt.Println(decimal128.New(3, 0))
	fmt.Println(decimal128.New(3, 2))
	// Output:
	// 0.03
	// 3
	// 300
}

func ExampleParse() {
	x, _ := decimal128.Parse("123.456")
	y, _ := decimal128.Parse("123_456.789e10")
	inf, _ := decimal128.Parse("-Inf")
	nan, _ := decimal128.Parse("NaN")
	fmt.Println(x)
	fmt.Println(y)
	fmt.Println(inf)
	fmt.Println(nan)
	// Output:
	// 123.456
	// 1.23456789e+15
	// -Inf
	// NaN
}

func ExampleRound() {
	x := decimal128.New(-123, -2)
	y := decimal128.New(789, -2)
	fmt.Println(decimal128.Round(x))
	fmt.Println(decimal128.Round(y))
	// Output:
	// -1
	// 8
}

func ExampleTrunc() {
	x := decimal128.New(-123, -2)
	y := decimal128.New(789, -2)
	fmt.Println(decimal128.Trunc(x))
	fmt.Println(decimal128.Trunc(y))
	// Output:
	// -1
	// 7
}

func ExampleDecimal_Add() {
	x := decimal128.New(3, 0)
	y := decimal128.New(2, -1)
	fmt.Printf("%g + %g = %g\n", x, y, x.Add(y))
	// Output:
	// 3 + 0.2 = 3.2
}

func ExampleDecimal_Append() {
	x := decimal128.New(3, 0)
	b := x.Append(nil, "010.5f")
	fmt.Printf("%s\n", b)
	// Output:
	// 0003.00000
}

func ExampleDecimal_Canonical() {
	x := decimal128.New(123, -1)
	y := decimal128.New(1230, -2)
	fmt.Printf("%g, %g\n", x, y)
	fmt.Printf("%t, %t\n", x.Equal(y), x == y)
	x = x.Canonical()
	y = y.Canonical()
	fmt.Printf("%g, %g\n", x, y)
	fmt.Printf("%t, %t\n", x.Equal(y), x == y)
	// Output:
	// 12.3, 12.3
	// true, false
	// 12.3, 12.3
	// true, true
}

func ExampleDecimal_Cmp() {
	x := decimal128.New(1, 0)
	y := decimal128.New(2, 0)
	r := x.Cmp(y)
	fmt.Printf("%g < %g = %t\n", x, y, r.Less())
	fmt.Printf("%g == %g = %t\n", x, y, r.Equal())
	fmt.Printf("%g > %g = %t\n", x, y, r.Greater())
	// Output:
	// 1 < 2 = true
	// 1 == 2 = false
	// 1 > 2 = false
}

func ExampleDecimal_Ceil() {
	x := decimal128.New(123456, -3)
	fmt.Println("unrounded:", x)
	fmt.Println("+2 places:", x.Ceil(2))
	fmt.Println(" 0 places:", x.Ceil(0))
	fmt.Println("-2 places:", x.Ceil(-2))
	// Output:
	// unrounded: 123.456
	// +2 places: 123.46
	//  0 places: 124
	// -2 places: 200
}

func ExampleDecimal_Floor() {
	x := decimal128.New(123456, -3)
	fmt.Println("unrounded:", x)
	fmt.Println("+2 places:", x.Floor(2))
	fmt.Println(" 0 places:", x.Floor(0))
	fmt.Println("-2 places:", x.Floor(-2))
	// Output:
	// unrounded: 123.456
	// +2 places: 123.45
	//  0 places: 123
	// -2 places: 100
}

func ExampleDecimal_Mul() {
	x := decimal128.New(3, 0)
	y := decimal128.New(2, -1)
	fmt.Printf("%g * %g = %g\n", x, y, x.Mul(y))
	// Output:
	// 3 * 0.2 = 0.6
}

func ExampleDecimal_Payload() {
	zero := decimal128.Decimal{}
	x := zero.Quo(zero)
	fmt.Printf("%g generated by %v\n", x, x.Payload())
	// Output:
	// NaN generated by Quo(Zero, Zero)
}

func ExampleDecimal_Quo() {
	x := decimal128.New(152, -1)
	y := decimal128.New(5, 0)
	fmt.Printf("%g / %g = %g\n", x, y, x.Quo(y))
	// Output:
	// 15.2 / 5 = 3.04
}

func ExampleDecimal_QuoRem() {
	x := decimal128.New(152, -1)
	y := decimal128.New(5, 0)
	q, r := x.QuoRem(y)
	fmt.Printf("%g / %g = (%g, %g)\n", x, y, q, r)
	// Output:
	// 15.2 / 5 = (3, 0.2)
}

func ExampleDecimal_Round() {
	x := decimal128.New(123456, -3)
	fmt.Println("unrounded:", x)
	fmt.Println("+2 places:", x.Round(2, decimal128.DefaultRoundingMode))
	fmt.Println(" 0 places:", x.Round(0, decimal128.DefaultRoundingMode))
	fmt.Println("-2 places:", x.Round(-2, decimal128.DefaultRoundingMode))
	// Output:
	// unrounded: 123.456
	// +2 places: 123.46
	//  0 places: 123
	// -2 places: 100
}

func ExampleDecimal_Sign() {
	x := decimal128.FromInt64(-5)
	fmt.Printf("% g.Sign() = %d\n", x, x.Sign())
	x = decimal128.FromInt64(0)
	fmt.Printf("% g.Sign() = %d\n", x, x.Sign())
	x = decimal128.FromInt64(5)
	fmt.Printf("% g.Sign() = %d\n", x, x.Sign())
	// Output:
	// -5.Sign() = -1
	//  0.Sign() = 0
	//  5.Sign() = 1
}

func ExampleDecimal_Sub() {
	x := decimal128.New(3, 0)
	y := decimal128.New(2, -1)
	fmt.Printf("%g - %g = %g\n", x, y, x.Sub(y))
	// Output:
	// 3 - 0.2 = 2.8
}
