summaryrefslogtreecommitdiff
path: root/src/types.c
blob: c9482c1d9b226a2c25f89476002f5a7b9f4753b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <math.h>

#include "osm/types.h"

OSMFloatBreakdown osm_float_to_break(OSMFloat f)
{
	OSMFloatBreakdown out;

	out.sign = f >> 63;
	out.mantissa = (f >> 52) & 0x7ff;
	out.fraction = f & 0xfffffffffffff;

	return out;
}

/*
 * WARNING: This code assumes that the compiler
 * supports IEEE 754 floating point numbers.
 *
 * Should probably be updated with more formats if I was
 * feeling frisky.
 *
 * Supports half, single, and double precision IEEE 754
 */
OSMFloatBreakdown osm_native_float_to_break(double d)
{
	OSMFloatBreakdown out = {0};

	switch(sizeof(double))
	{
		case 2: {
			uint16_t bits = *(uint16_t *) &d;
			out.sign = bits >> 15;
		} break;

		case 4: {
			uint32_t bits = * (uint32_t *) &d;
			out.sign = bits >> 31;
		} break;

		case 8: {
			uint64_t bits = * (uint64_t *) &d;
			out = osm_float_to_break(bits);
		} break;

		default:
			break;
	}

	return out;
}

OSMFloat osm_break_to_float(OSMFloatBreakdown b)
{
	OSMFloat out;
	
	if (b.sign)
		out = 1;
	out = out << 63;

	out |= (OSMFloat)(b.mantissa & 0x7ff) << 52;

	out |= b.fraction & 0xfffffffffffff;

	return out;
}

/*
 * WARNING: This code assumes that the compiler
 * supports IEEE 754 floating point numbers.
 *
 * Should probably be updated with more formats if I was
 * feeling frisky.
 */
double osm_break_to_native_float(OSMFloatBreakdown b)
{
	double out = 0;

	switch(sizeof(double))
	{
		case 2: {
		} break;
		
		case 4: {
		} break;
		
		case 8: {
			OSMFloat f = osm_break_to_float(b);
			out = * (double *) &f;
		} break;
		
		default:
			break;
	}

	if (b.sign)
		out = -out;

	return out;
}

double osm_float_to_native(OSMFloat f)
{
	return
		osm_break_to_native_float(
			osm_float_to_break(f)
		);
}

OSMFloat osm_native_to_float(double d)
{
	return
		osm_break_to_float(
			osm_native_float_to_break(d)
		);
}