1 /* Copyright (C) 2008, 2009 Vincent Penquerc'h.
2    This file is part of the Kate codec library.
3    Written by Vincent Penquerc'h.
4 
5    Use, distribution and reproduction of this library is governed
6    by a BSD style source license included with this source in the
7    file 'COPYING'. Please read these terms before distributing. */
8 
9 
10 #define KATE_INTERNAL
11 #include "kate_internal.h"
12 
13 #ifdef HAVE_STDLIB_H
14 #include <stdlib.h>
15 #endif
16 #include "kate/kate.h"
17 #include "kate_bitwise.h"
18 #include "kate_fp.h"
19 
20 #define MERGE_STREAMS
21 #define MERGE_STREAMS_COUNT_THRESHOLD 0
22 /* #define WRITE_64_IN_TWO_32 */
23 
24 #define FLOAT_SCALE ((kate_float)(((kate_fp)1)<<(KATE_FP_FRAC)))
25 #define kate_fp_bits (sizeof(kate_fp)*8)
26 #define kate_fp_cut_bits ((kate_fp_bits)/2-1)
27 #define kate_fp_cut_bits_bits (kate_fp_bits==16?3:kate_fp_bits==32?4:kate_fp_bits==64?5:8)
28 #define kate_fp_sign_bit (kate_fp_bits==16?0x8000:kate_fp_bits==32?0x80000000:kate_fp_bits==64?((kate_int64_t)-1):0)
29 
f2kfp(kate_float f)30 static inline kate_fp f2kfp(kate_float f)
31 {
32   kate_fp test=(kate_fp)(f*(FLOAT_SCALE*2));
33   if (test&1)
34     return (kate_fp)(f*FLOAT_SCALE+(kate_float)0.5);
35   else
36     return (kate_fp)(f*FLOAT_SCALE);
37 }
38 
kfp2f(kate_fp v)39 static inline kate_float kfp2f(kate_fp v)
40 {
41   return v/FLOAT_SCALE;
42 }
43 
kate_fp_scan(size_t count,const kate_fp * values,size_t streams,int * head,int * tail)44 static int kate_fp_scan(size_t count,const kate_fp *values,size_t streams,int *head,int *tail)
45 {
46   kate_fp v=0,tst;
47   size_t n;
48 
49   if (!values || !head || !tail) return KATE_E_INVALID_PARAMETER;
50 
51   while (count--) {
52     kate_fp value=*values;
53     values+=streams;
54     if (value<0) value=-value;
55     v|=value;
56   }
57 
58   tst=v;
59   for (n=0;n<kate_fp_cut_bits;++n) {
60     if (tst&kate_fp_sign_bit) break;
61     tst<<=1;
62   }
63   *head=n;
64 
65   tst=v;
66   for (n=0;n<kate_fp_cut_bits;++n) {
67     if (tst&1) break;
68     tst>>=1;
69   }
70   *tail=n;
71 
72   return 0;
73 }
74 
75 #if 0
76 static int kate_fp_scan_constant(size_t count,const kate_fp *values,size_t streams,kate_fp constant)
77 {
78   while (count--) {
79     kate_fp value=*values;
80     values+=streams;
81     if (value!=constant) return 1;
82   }
83   return 0;
84 }
85 #endif
86 
87 /* need 8 bits, then a bit for sign and kate_fp_bits-(t+h) per value */
kate_fp_encode(size_t count,const kate_fp * values,size_t streams,kate_pack_buffer * kpb)88 int kate_fp_encode(size_t count,const kate_fp *values,size_t streams,kate_pack_buffer *kpb)
89 {
90   int head,tail;
91   int bits;
92 
93   if (!kpb || count==0 || !values) return KATE_E_INVALID_PARAMETER;
94 
95   kate_fp_scan(count,values,streams,&head,&tail);
96   kate_pack_write(kpb,head,kate_fp_cut_bits_bits); /* can be between 0 and kate_fp_cut_bits */
97   kate_pack_write(kpb,tail,kate_fp_cut_bits_bits); /* can be between 0 and kate_fp_cut_bits */
98   bits=kate_fp_bits-tail-head;
99   while (count--) {
100     kate_fp v=*values++;
101     if (head>0) {
102       if (v<0) {
103         kate_pack_write(kpb,1,1);
104         v=-v;
105       }
106       else {
107         kate_pack_write(kpb,0,1);
108       }
109     }
110     v>>=tail;
111 #ifdef WRITE_64_IN_TWO_32
112     if (bits>32) {
113       kate_pack_write(kpb,v,32);
114       v>>=32;
115       kate_pack_write(kpb,v,bits-32); /* will autoclip the head */
116     }
117     else
118 #endif
119     {
120       kate_pack_write(kpb,v,bits); /* will autoclip the head */
121     }
122   }
123 
124   return 0;
125 }
126 
kate_fp_encode_kate_float(size_t count,const kate_float * values,size_t streams,kate_pack_buffer * kpb)127 int kate_fp_encode_kate_float(size_t count,const kate_float *values,size_t streams,kate_pack_buffer *kpb)
128 {
129   kate_fp *fp_values;
130   size_t s,n;
131   int ret;
132 
133   if (count*streams==0) return 0;
134 
135   if (streams>1 && count>MERGE_STREAMS_COUNT_THRESHOLD) {
136 #ifdef MERGE_STREAMS
137     count*=streams;
138     streams=1;
139     kate_pack_write(kpb,1,1);
140 #else
141     kate_pack_write(kpb,0,1);
142 #endif
143   }
144 
145   fp_values=(kate_fp*)kate_checked_malloc(count,sizeof(kate_fp));
146   if (!fp_values) return KATE_E_OUT_OF_MEMORY;
147 
148   for (s=0;s<streams;++s) {
149     for (n=0;n<count;++n) {
150       kate_float v=values[n*streams+s];
151       fp_values[n]=f2kfp(v);
152     }
153 
154     ret=kate_fp_encode(count,fp_values,1,kpb);
155     if (ret<0) {
156       kate_free(fp_values);
157       return ret;
158     }
159   }
160 
161   kate_free(fp_values);
162 
163   return 0;
164 }
165 
kate_fp_decode(size_t count,kate_fp * values,size_t streams,kate_pack_buffer * kpb)166 int kate_fp_decode(size_t count,kate_fp *values,size_t streams,kate_pack_buffer *kpb)
167 {
168   int head,tail,bits;
169   kate_fp v;
170 
171   if (!kpb || count==0 || !values) return KATE_E_INVALID_PARAMETER;
172 
173   head=kate_pack_read(kpb,kate_fp_cut_bits_bits);
174   tail=kate_pack_read(kpb,kate_fp_cut_bits_bits);
175   bits=kate_fp_bits-head-tail;
176   while (count--) {
177     int sign=0;
178     if (head>0) {
179       sign=kate_pack_read1(kpb);
180     }
181 #ifdef WRITE_64_IN_TWO_32
182     if (bits>32) {
183       kate_fp low=kate_pack_read(kpb,32);
184       v=kate_pack_read(kpb,bits-32);
185       v<<=32;
186       v|=low;
187     }
188     else
189 #endif
190     {
191       v=kate_pack_read(kpb,bits);
192     }
193     v<<=tail;
194     if (sign) v=-v;
195     *values=v;
196     values+=streams;
197   }
198 
199   return 0;
200 }
201 
kate_fp_decode_kate_float(size_t count,kate_float * values,size_t streams,kate_pack_buffer * kpb)202 int kate_fp_decode_kate_float(size_t count,kate_float *values,size_t streams,kate_pack_buffer *kpb)
203 {
204   kate_fp *fp_values;
205   size_t s,n;
206   int ret;
207 
208   if (count*streams==0) return 0;
209 
210   if (streams>1 && count>MERGE_STREAMS_COUNT_THRESHOLD) {
211     if (kate_pack_read1(kpb)) {
212       count*=streams;
213       streams=1;
214     }
215   }
216 
217   fp_values=(kate_fp*)kate_checked_malloc(count,sizeof(kate_fp));
218   if (!fp_values) return KATE_E_OUT_OF_MEMORY;
219 
220   for (s=0;s<streams;++s) {
221     ret=kate_fp_decode(count,fp_values,1,kpb);
222     if (ret<0) {
223       kate_free(fp_values);
224       return ret;
225     }
226 
227     for (n=0;n<count;++n) {
228       values[n*streams+s]=kfp2f(fp_values[n]);
229     }
230   }
231 
232   kate_free(fp_values);
233 
234   return 0;
235 }
236 
237