// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 float16

import (
	
	
	
	
)

// Num represents a half-precision floating point value (float16)
// stored on 16 bits.
//
// See https://en.wikipedia.org/wiki/Half-precision_floating-point_format for more informations.
type Num struct {
	bits uint16
}

var (
	MaxNum = Num{bits: 0b0111101111111111}
	MinNum = MaxNum.Negate()
)

// New creates a new half-precision floating point value from the provided
// float32 value.
func ( float32) Num {
	 := math.Float32bits()
	 := uint16(( >> 31) & 0x1)
	 := ( >> 23) & 0xff
	 := int16() - 127 + 15
	 := uint16(>>13) & 0x3ff
	switch {
	case  == 0:
		 = 0
	case  == 0xff:
		 = 0x1f
	case  > 0x1e:
		 = 0x1f
		 = 0
	case  < 0x01:
		 = 0
		 = 0
	}
	return Num{bits: ( << 15) | uint16(<<10) | }
}

func ( Num) ( fmt.State,  rune) {
	fmt.Fprintf(, fmt.FormatString(, ), .Float32())
}

func ( Num) () float32 {
	 := uint32((.bits >> 15) & 0x1)
	 := (.bits >> 10) & 0x1f
	 := uint32() + 127 - 15
	 := uint32(.bits & 0x3ff)
	switch  {
	case 0:
		 = 0
	case 0x1f:
		 = 0xff
	}
	return math.Float32frombits(( << 31) | ( << 23) | ( << 13))
}

func ( Num) () Num {
	return Num{bits: .bits ^ 0x8000}
}

func ( Num) ( Num) Num {
	return New(.Float32() + .Float32())
}

func ( Num) ( Num) Num {
	return New(.Float32() - .Float32())
}

func ( Num) ( Num) Num {
	return New(.Float32() * .Float32())
}

func ( Num) ( Num) Num {
	return New(.Float32() / .Float32())
}

// Equal returns true if the value represented by n is == other
func ( Num) ( Num) bool {
	return .Float32() == .Float32()
}

// Greater returns true if the value represented by n is > other
func ( Num) ( Num) bool {
	return .Float32() > .Float32()
}

// GreaterEqual returns true if the value represented by n is >= other
func ( Num) ( Num) bool {
	return .Float32() >= .Float32()
}

// Less returns true if the value represented by n is < other
func ( Num) ( Num) bool {
	return .Float32() < .Float32()
}

// LessEqual returns true if the value represented by n is <= other
func ( Num) ( Num) bool {
	return .Float32() <= .Float32()
}

// Max returns the largest Decimal128 that was passed in the arguments
func ( Num,  ...Num) Num {
	 := 
	for ,  := range  {
		if .Greater() {
			 = 
		}
	}
	return 
}

// Min returns the smallest Decimal128 that was passed in the arguments
func ( Num,  ...Num) Num {
	 := 
	for ,  := range  {
		if .Less() {
			 = 
		}
	}
	return 
}

// Cmp compares the numbers represented by n and other and returns:
//
//	+1 if n > other
//	 0 if n == other
//	-1 if n < other
func ( Num) ( Num) int {
	switch {
	case .Greater():
		return 1
	case .Less():
		return -1
	}
	return 0
}

func ( Num) () Num {
	switch .Sign() {
	case -1:
		return .Negate()
	}
	return 
}

func ( Num) () int {
	if .IsZero() {
		return 0
	} else if .Signbit() {
		return -1
	}
	return 1
}

func ( Num) () bool { return (.bits & 0x8000) != 0 }

func ( Num) () bool { return (.bits & 0x7fff) > 0x7c00 }

func ( Num) () bool { return (.bits & 0x7c00) == 0x7c00 }

func ( Num) () bool { return (.bits & 0x7fff) == 0 }

func ( Num) () uint16 { return uint16(.bits) }
func ( Num) () string { return strconv.FormatFloat(float64(.Float32()), 'g', -1, 32) }

func () Num { return Num{bits: 0x7c00} }

func () Num { return Num{bits: 0x7fff} }

func ( uint16) Num { return Num{bits: } }

func ( []byte) Num {
	return Num{bits: binary.LittleEndian.Uint16()}
}

func ( Num) ( []byte) {
	binary.LittleEndian.PutUint16(, .bits)
}

func ( Num) () []byte {
	 := make([]byte, 2)
	.PutLEBytes()
	return 
}