1 /* This code is part of the tng compression routines.
2  *
3  * Written by Daniel Spangberg
4  * Copyright (c) 2010, 2013, The GROMACS development team.
5  *
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the Revised BSD License.
9  */
10 
11 #include <stdio.h>
12 #include <math.h>
13 #include "../../include/compression/fixpoint.h"
14 
15 #define MAX32BIT 4294967295UL
16 #define MAX31BIT 2147483647UL
17 #define SIGN32BIT 2147483648UL
18 
19 /* Conversion routines from / to double precision */
20 
21 /* Positive double to 32 bit fixed point value */
Ptngc_ud_to_fix_t(double d,const double max)22 fix_t Ptngc_ud_to_fix_t(double d, const double max)
23 {
24   fix_t val;
25   if (d<0.)
26     d=0.;
27   if (d>max)
28     d=max;
29   val=(fix_t)(MAX32BIT*(d/max));
30   if (val>MAX32BIT)
31     val=MAX32BIT;
32   return val;
33 }
34 
35 /* double to signed 32 bit fixed point value */
Ptngc_d_to_fix_t(double d,const double max)36 fix_t Ptngc_d_to_fix_t(double d, const double max)
37 {
38   fix_t val;
39   int sign=0;
40   if (d<0.)
41     {
42       sign=1;
43       d=-d;
44     }
45   if (d>max)
46     d=max;
47   val=(fix_t)(MAX31BIT*(d/max));
48   if (val>MAX31BIT)
49     val=MAX31BIT;
50   if (sign)
51     val|=SIGN32BIT;
52   return val;
53 }
54 
55 
56 /* 32 bit fixed point value to positive double */
Ptngc_fix_t_to_ud(fix_t f,const double max)57 double Ptngc_fix_t_to_ud(fix_t f, const double max)
58 {
59   return (double)f*(max/MAX32BIT);
60 }
61 
62 /* signed 32 bit fixed point value to double */
Ptngc_fix_t_to_d(fix_t f,const double max)63 double Ptngc_fix_t_to_d(fix_t f, const double max)
64 {
65   int sign=0;
66   double d;
67   if (f&SIGN32BIT)
68     {
69       sign=1;
70       f&=MAX31BIT;
71     }
72   d=(double)f*(max/MAX31BIT);
73   if (sign)
74     d=-d;
75   return d;
76 }
77 
78 
79 /* Convert a floating point variable to two 32 bit integers with range
80    -2.1e9 to 2.1e9 and precision to somewhere around 1e-9. */
Ptngc_d_to_i32x2(double d,fix_t * hi,fix_t * lo)81 void Ptngc_d_to_i32x2(double d, fix_t *hi, fix_t *lo)
82 {
83   int sign=0;
84   double frac;
85   double ent;
86   fix_t val,vallo;
87   if (d<0.)
88     {
89       sign=1;
90       d=-d;
91     }
92   /* First the integer part */
93   ent=floor(d);
94   /* Then the fractional part */
95   frac=d-ent;
96 
97   val=(fix_t)ent;
98   if (sign)
99     val|=SIGN32BIT;
100 
101   vallo=Ptngc_ud_to_fix_t(frac,1.);
102 
103   *hi=val;
104   *lo=vallo;
105 }
106 
107 /* Convert two 32 bit integers to a floating point variable
108    -2.1e9 to 2.1e9 and precision to somewhere around 1e-9. */
Ptngc_i32x2_to_d(fix_t hi,fix_t lo)109 double Ptngc_i32x2_to_d(fix_t hi, fix_t lo)
110 {
111   double ent,frac=0.;
112   double val=0.;
113   int sign=0;
114   if (hi&SIGN32BIT)
115     {
116       sign=1;
117       hi&=MAX31BIT;
118     }
119   ent=(double)hi;
120   frac=Ptngc_fix_t_to_ud(lo,1.);
121   val=ent+frac;
122   if (sign)
123     val=-val;
124   return val;
125 }
126 
127