aboutsummaryrefslogtreecommitdiff
path: root/bcdfp.c
blob: 76157c18593d2992924612675a86aa1209b4a234 (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
#include <string.h>
#include "bcdfp.h"

extern void die(const char *msg);

unsigned char bcd2int(unsigned char bcd) {
	return (bcd >> 4) * 10 + (bcd & 0x0f);
}

unsigned char int2bcd(unsigned char i) {
	return ((i / 10) << 4) | (i % 10);
}

unsigned short fp2int(const unsigned char *fp) {
	unsigned short result = 0;

	/* examine the exponent/sign byte */
	if(fp[0] == 0) return 0; /* special case */
	if(fp[0] & 0x80) die("negative numbers not supported");

	switch(fp[0]) {
		case 0x40:
			result = bcd2int(fp[1]); break;
		case 0x41:
			result = bcd2int(fp[1]) * 100 + bcd2int(fp[2]); break;
		case 0x42:
			result = bcd2int(fp[1]) * 10000 + bcd2int(fp[2]) * 100 + bcd2int(fp[3]); break;
		default:
			die("number out of range"); break;
	}

	return result;
}

void int2fp(unsigned short num, unsigned char *fp) {
	memset(fp, 0, 6);

	if(num == 0) return;

	if(num >= 10000) {
		fp[0] = 0x42;
		fp[3] = int2bcd(num % 100);
		num /= 100;
		fp[2] = int2bcd(num % 100);
		num /= 100;
		fp[1] = int2bcd(num);
	} else if(num >= 100) {
		fp[0] = 0x41;
		fp[2] = int2bcd(num % 100);
		num /= 100;
		fp[1] = int2bcd(num);
	} else {
		fp[0] = 0x40;
		fp[1] = int2bcd(num);
	}
}