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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/* This code is part of the tng compression routines.
*
* Written by Daniel Spangberg
* Copyright (c) 2010, 2013, The GROMACS development team.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <math.h>
#include "fixpoint.h"
#define MAX32BIT 4294967295UL
#define MAX31BIT 2147483647UL
#define SIGN32BIT 2147483648UL
/* Conversion routines from / to double precision */
/* Positive double to 32 bit fixed point value */
fix_t Ptngc_ud_to_fix_t(double d,double max)
{
fix_t val;
if (d<0.)
d=0.;
if (d>max)
d=max;
val=(fix_t)(MAX32BIT*(d/max));
if (val>MAX32BIT)
val=MAX32BIT;
return val;
}
/* double to signed 32 bit fixed point value */
fix_t Ptngc_d_to_fix_t(double d,double max)
{
fix_t val;
int sign=0;
if (d<0.)
{
sign=1;
d=-d;
}
if (d>max)
d=max;
val=(fix_t)(MAX31BIT*(d/max));
if (val>MAX31BIT)
val=MAX31BIT;
if (sign)
val|=SIGN32BIT;
return val;
}
/* 32 bit fixed point value to positive double */
double Ptngc_fix_t_to_ud(fix_t f, double max)
{
return (double)f*(max/MAX32BIT);
}
/* signed 32 bit fixed point value to double */
double Ptngc_fix_t_to_d(fix_t f, double max)
{
int sign=0;
double d;
if (f&SIGN32BIT)
{
sign=1;
f&=MAX31BIT;
}
d=(double)f*(max/MAX31BIT);
if (sign)
d=-d;
return d;
}
/* Convert a floating point variable to two 32 bit integers with range
-2.1e9 to 2.1e9 and precision to somewhere around 1e-9. */
void Ptngc_d_to_i32x2(double d, fix_t *hi, fix_t *lo)
{
int sign=0;
double frac;
double ent;
fix_t val,vallo;
if (d<0.)
{
sign=1;
d=-d;
}
/* First the integer part */
ent=floor(d);
/* Then the fractional part */
frac=d-ent;
val=(fix_t)ent;
if (sign)
val|=SIGN32BIT;
vallo=Ptngc_ud_to_fix_t(frac,1.);
*hi=val;
*lo=vallo;
}
/* Convert two 32 bit integers to a floating point variable
-2.1e9 to 2.1e9 and precision to somewhere around 1e-9. */
double Ptngc_i32x2_to_d(fix_t hi, fix_t lo)
{
double ent,frac=0.;
double val=0.;
int sign=0;
if (hi&SIGN32BIT)
{
sign=1;
hi&=MAX31BIT;
}
ent=(double)hi;
frac=Ptngc_fix_t_to_ud(lo,1.);
val=ent+frac;
if (sign)
val=-val;
return val;
}
|