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