package math

/*
	VAX Single-precision (F) Floating-point Format

	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	|                f2                     |                f3                     |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	| 15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	| s  |           e1                     | e2 |                f1                |
	+----+----------------------------------+----+----------------------------------+

*/

// VaxFfloat32frombits ...
func VaxFfloat32frombits(b uint32) float32 {

	var (
		exp     int
		s, e, m uint32
	)

	s = (b & 0x00008000) >> 15
	s <<= IEEE32SignPos

	exp = int((b & 0x00007f80) >> 7)
	exp -= 128
	exp -= 1

	e = ToIEEE32Exponent(exp)

	m |= (b & 0x0000007f) << 16
	m |= (b & 0xffff0000) >> 16

	return Float32frombits(s | e | m)

}

// VaxFfloat32bits ...
func VaxFfloat32bits(v float32) uint32 {

	var (
		b uint32 = Float32bits(v)

		exp     int
		s, e, m uint32
	)

	s = (b & IEEE32Sign) >> (IEEE32SignPos - 15)

	exp = IEEE32Exponent(b)
	exp += 1
	exp += 128

	e = uint32(exp) & 0x000000ff
	e <<= 7

	m |= (b & 0x007f0000) >> 16
	m |= (b & 0x0000ffff) << 16

	return s | e | m
}

/*
	VAX Double-precision (G) Floating-point Format

	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	| 63 | 62 | 61 | 60 | 59 | 58 | 57 | 56 | 55 | 54 | 53 | 52 | 51 | 50 | 49 | 48 |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	|                                         f4                                    |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	| 47 | 46 | 45 | 44 | 43 | 42 | 41 | 40 | 39 | 38 | 37 | 36 | 35 | 34 | 33 | 32 |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	|                                         f3                                    |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	| 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	|                                         f2                                    |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	| 15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
	+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
	|  s |           e                                          |      f1           |
	+----+------------------------------------------------------+-------------------+

*/

// VaxGfloat64frombits ...
func VaxGfloat64frombits(b uint64) float64 {

	var (
		exp     int
		s, e, m uint64
	)

	s = (b & 0x0000000000008000) >> 15
	s <<= IEEE64SignPos

	exp = int((b & 0x0000000000007ff0) >> 4)
	exp -= 1024
	exp -= 1

	e = ToIEEE64Exponent(exp)

	m |= (b & 0x000000000000000f) << 48
	m |= (b & 0x00000000ffff0000) << 16
	m |= (b & 0x0000ffff00000000) >> 16
	m |= (b & 0xffff000000000000) >> 48
	m &= IEEE64Mantissa

	return Float64frombits(s | e | m)

}

// VaxGfloat64bits ...
func VaxGfloat64bits(v float64) uint64 {

	var (
		b uint64 = Float64bits(v)

		exp     int
		s, e, m uint64
	)

	exp = IEEE64Exponent(b)
	exp += 1
	exp += 1024

	s = ((b & IEEE64Sign) >> (IEEE64SignPos - 15))

	e = uint64(exp) << 4

	m |= (b & 0x000f000000000000) >> 48
	m |= (b & 0x0000ffff00000000) >> 16
	m |= (b & 0x00000000ffff0000) << 16
	m |= (b & 0x000000000000ffff) << 48

	return (s | e | m)
}

var Vax = floatFormat{
	float32frombits: VaxFfloat32frombits,
	float32bits:     VaxFfloat32bits,
	float64frombits: VaxGfloat64frombits,
	float64bits:     VaxGfloat64bits,
}
