1 /*
2 This Software is provided under the Zope Public License (ZPL) Version 2.1.
3
4 Copyright (c) 2009 - 2013 by the mingw-w64 project
5
6 See the AUTHORS file for the list of contributors to the mingw-w64 project.
7
8 This license has been certified as open source. It has also been designated
9 as GPL compatible by the Free Software Foundation (FSF).
10
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions are met:
13
14 1. Redistributions in source code must retain the accompanying copyright
15 notice, this list of conditions, and the following disclaimer.
16 2. Redistributions in binary form must reproduce the accompanying
17 copyright notice, this list of conditions, and the following disclaimer
18 in the documentation and/or other materials provided with the
19 distribution.
20 3. Names of the copyright holders must not be used to endorse or promote
21 products derived from this software without prior written permission
22 from the copyright holders.
23 4. The right to distribute this software or to use it for any purpose does
24 not give you the right to use Servicemarks (sm) or Trademarks (tm) of
25 the copyright holders. Use of them is covered by separate agreement
26 with the copyright holders.
27 5. If any files are modified, you must cause the modified files to carry
28 prominent notices stating that you changed the files and the date of
29 any change.
30
31 Disclaimer
32
33 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
34 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
36 EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
37 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
39 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 */
44
45 /*
46 * Prelim Encoder/Decoder Test
47 * Build with -std=gnu99 -Wall -Wextra -Wformat -Wstrict-aliasing -Wshadow -Wpacked \
48 * -Winline -Wimplicit-function-declaration -Wmissing-noreturn -Wmissing-prototypes \
49 * -g -O2 -m32 -std=gnu99 -frounding-math -fsignaling-nans -Wno-inline -DCONFIG_32 \
50 * -DPPRO -DASM -Dmpdecimal_header=\"mpdecimal-i686.h\" -fno-strict-aliasing \
51 * -Wno-unused-function
52 */
53
54 #include <stdio.h>
55 #include <inttypes.h>
56 #include "dfp_internal.h"
57 #include mpdecimal_header
58
59 static const _Decimal32 dec32 = 0.0DF;
60 static const _Decimal64 dec64 = 0.0DD;
61 static const _Decimal128 dec128 = 0.0DL;
62
print_mpd(const mpd_t * in)63 static void print_mpd(const mpd_t *in){
64 printf("----\n");
65 printf("flags: %d\n",in->flags);
66 printf("exp: %I64d\n",(uint64_t)in->exp);
67 printf("digits: %I64d\n",(uint64_t)in->digits);
68 printf("trail: %I64d\n",(uint64_t)mpd_trail_zeros(in));
69 printf("len: %I64d\n",(uint64_t)in->len);
70 printf("alloc: %I64d\n",(uint64_t)in->alloc);
71 printf("data: ");
72 for(mpd_ssize_t i = 0; i < in->len; i++){
73 printf("[%09I64x]",(uint64_t)in->data[i]);
74 }
75 printf("\n");
76 printf("----\n");
77 }
78
print_dec32(const _Decimal32 * in)79 static void print_dec32(const _Decimal32 *in){
80 ud32 ret;
81 ret.d = *in;
82 printf("----\n");
83 printf("sign %x\n", ret.t0.sign);
84 printf("bits %x\n", ret.t0.bits);
85 printf("flag %x\n", ret.t0.flag);
86 if(ret.t0.bits == 0x3){
87 printf("exp %d\n", ret.t2.exponent);
88 printf("mantissa %d\n", ret.t2.mantissa);
89 } else {
90 printf("exp %d\n", ret.t1.exponent);
91 printf("mantissa %d\n", ret.t1.mantissa);
92 }
93 printf("----\n");
94 }
95
print_dec64(const _Decimal64 * in)96 static void print_dec64(const _Decimal64 *in){
97 ud64 ret;
98 ret.d = *in;
99 printf("----\n");
100 printf("sign %x\n", ret.t0.sign);
101 printf("bits %x\n", ret.t0.bits);
102 printf("flag %x\n", ret.t0.flag);
103 if(ret.t0.bits == 0x3){
104 printf("exp %d\n", ret.t2.exponent);
105 printf("mantissa %I64u\n", (uint64_t)ret.t2.mantissa);
106 } else {
107 printf("exp %d\n", ret.t1.exponent);
108 printf("mantissa %I64u\n", (uint64_t)ret.t1.mantissa);
109 }
110 printf("----\n");
111 }
112
print_dec128(const _Decimal128 * in)113 static void print_dec128(const _Decimal128 *in){
114 ud128 ret;
115 ret.d = *in;
116 printf("----\n");
117 printf("sign %x\n", ret.t0.sign);
118 printf("bits %x\n", ret.t0.bits);
119 printf("flag %x\n", ret.t0.flag);
120 if(ret.t0.bits == 0x3){
121 printf("exp %d\n", ret.t2.exponent);
122 printf("mantissaL %I64u\n", (uint64_t)ret.t2.mantissaL);
123 printf("mantissaH %I64u\n", (uint64_t)ret.t2.mantissaH);
124 } else {
125 printf("exp %d\n", ret.t1.exponent);
126 printf("mantissaL %I64u\n", (uint64_t)ret.t1.mantissaL);
127 printf("mantissaH %I64u\n", (uint64_t)ret.t1.mantissaH);
128 }
129 printf("----\n");
130 }
131
132
dec_to_mpd_conv(mpd_context_t * ctx,mpd_t * result,const int64_t significand_low,const int64_t exponent_part)133 static void dec_to_mpd_conv(mpd_context_t * ctx, mpd_t *result, const int64_t significand_low, const int64_t exponent_part){
134 uint32_t status = 0;
135 mpd_t *ten, *exp_pow, *exp_partmpd, *significand_partmpd;
136 ten = mpd_qnew();
137 exp_pow = mpd_qnew();
138 exp_partmpd = mpd_qnew();
139 significand_partmpd = mpd_qnew();
140
141 mpd_qset_i64(ten,10LL,ctx,&status);
142 mpd_qset_i64(significand_partmpd,significand_low,ctx,&status);
143 mpd_qset_i64(exp_partmpd,exponent_part,ctx,&status);
144 mpd_qpow(exp_pow,ten,exp_partmpd,ctx,&status);
145 mpd_qmul(result,significand_partmpd,exp_pow,ctx,&status);
146
147 mpd_del(ten);
148 mpd_del(exp_pow);
149 mpd_del(exp_partmpd);
150 mpd_del(significand_partmpd);
151 }
152
dec128_to_mpd_conv(mpd_context_t * ctx,mpd_t * result,const uint64_t significand_low,const int64_t significand_high,const int64_t exponent_part)153 static void dec128_to_mpd_conv(mpd_context_t * ctx, mpd_t *result, const uint64_t significand_low, const int64_t significand_high, const int64_t exponent_part){
154 uint32_t status = 0;
155 mpd_t *ten, *sig1, *sig2, *stemp, *sig, *s64, *exp_pow, *exp_partmpd;
156 ten = mpd_qnew();
157 s64 = mpd_qnew();
158 sig1 = mpd_qnew();
159 sig2 = mpd_qnew();
160 stemp = mpd_qnew();
161 sig = mpd_qnew();
162 exp_pow = mpd_qnew();
163 exp_partmpd = mpd_qnew();
164 mpd_qset_i64(ten,10LL,ctx,&status);
165 /* 2^64 */
166 mpd_qset_string(s64,"18446744073709551616",ctx,&status);
167 mpd_qset_u64(sig1,significand_low,ctx,&status);
168 mpd_qset_i64(sig2,significand_high,ctx,&status);
169 mpd_qmul(stemp,sig2,s64,ctx,&status);
170 mpd_qadd(sig,stemp,sig1,ctx,&status);
171 mpd_qset_i64(exp_partmpd,exponent_part,ctx,&status);
172 mpd_qpow(exp_pow,ten,exp_partmpd,ctx,&status);
173 mpd_qmul(result,sig,exp_pow,ctx,&status);
174 mpd_del(ten);
175 mpd_del(sig1);
176 mpd_del(sig2);
177 mpd_del(sig);
178 mpd_del(stemp);
179 mpd_del(s64);
180 mpd_del(exp_pow);
181 mpd_del(exp_partmpd);
182 }
183
dec128_to_mpd(mpd_context_t * ctx,mpd_t * result,const _Decimal128 deci)184 static uint32_t dec128_to_mpd(mpd_context_t * ctx, mpd_t *result, const _Decimal128 deci){
185 int64_t significand2, exp_part;
186 uint64_t significand1;
187 ud128 in = {.d = deci};
188
189 if(in.t0.bits == 0x3){ /*case 11 */
190 /* should not enter here */
191 exp_part = in.t2.exponent;
192 significand1 = in.t2.mantissaL;
193 significand2 = (in.t2.mantissaH | (0x1ULL << 49)) * ((in.t2.sign) ? -1 : 1);
194 } else {
195 exp_part = in.t1.exponent;
196 significand1 = in.t1.mantissaL;
197 significand2 = in.t1.mantissaH * ((in.t1.sign) ? -1 : 1);
198 }
199
200 printf("%I64d %I64d\n", significand1, significand2);
201
202 exp_part -= 6176; /* exp bias */
203 dec128_to_mpd_conv(ctx, result, significand1, significand2, exp_part);
204 return 0;
205 }
206
dec64_to_mpd(mpd_context_t * ctx,mpd_t * result,const _Decimal64 deci)207 static uint32_t dec64_to_mpd(mpd_context_t * ctx, mpd_t *result, const _Decimal64 deci){
208 int64_t significand, exp_part;
209 ud64 in = {.d = deci};
210
211 if(in.t0.bits == 0x3){ /*case 11 */
212 exp_part = in.t2.exponent;
213 significand = (in.t2.mantissa | (0x1ULL << 53)) * ((in.t2.sign) ? -1 : 1);
214 } else {
215 exp_part = in.t1.exponent;
216 significand = in.t1.mantissa * ((in.t1.sign) ? -1 : 1);
217 }
218 exp_part -= 398; /* exp bias */
219 dec_to_mpd_conv(ctx, result, significand, exp_part);
220 return 0;
221 }
222
dec32_to_mpd(mpd_context_t * ctx,mpd_t * result,const _Decimal32 deci)223 static uint32_t dec32_to_mpd(mpd_context_t * ctx, mpd_t *result, const _Decimal32 deci){
224 int64_t significand, exp_part;
225 ud32 in = {.d = deci};
226
227 if(in.t0.bits == 0x3){ /*case 11 */
228 exp_part = in.t2.exponent;
229 significand = (in.t2.mantissa | (0x1ULL << 23)) * ((in.t2.sign) ? -1 : 1);
230 } else {
231 exp_part = in.t1.exponent;
232 significand = in.t1.mantissa * ((in.t1.sign) ? -1 : 1);
233 }
234 exp_part -= 101; /* exp bias */
235 dec_to_mpd_conv(ctx, result, significand, exp_part);
236 return 0;
237 }
238
mpd_to_dec32(mpd_t * in)239 static _Decimal32 mpd_to_dec32(mpd_t *in){
240 uint32_t exp_part, significand;
241 uint32_t status = 0;
242 ud32 ret;
243 mpd_context_t ctx;
244 uint16_t *bases_data;
245 size_t bases;
246
247 mpd_ieee_context(&ctx,MPD_DECIMAL32);
248 mpd_qfinalize(in, &ctx,&status);
249
250 exp_part = in->exp + (uint32_t)mpd_trail_zeros(in) + 101LL; /* rough guess? */
251 in->exp = 0;
252 bases = mpd_sizeinbase(in, UINT16_MAX+1);
253 bases_data = __mingw_dfp_get_globals()->mpd_callocfunc(bases < 2 ? 2 : bases,sizeof(uint16_t));
254 mpd_qexport_u16(bases_data,bases,UINT16_MAX+1,in,&status);
255 significand = bases_data[0] | (uint32_t)bases_data[1] << 16 ;
256 __mingw_dfp_get_globals()->mpd_free(bases_data);
257 ret.t0.sign = mpd_isnegative(in);
258 if((significand & (0x7ULL << 21)) == (0x1ULL << 23)) { /* 100 MSB? */
259 ret.t2.bits = 0x3;
260 ret.t2.mantissa = significand;
261 ret.t2.exponent = exp_part;
262 } else {
263 ret.t1.mantissa = significand;
264 ret.t1.exponent = exp_part;
265 }
266 return ret.d;
267 }
268
mpd_to_dec64(mpd_t * in)269 static _Decimal64 mpd_to_dec64(mpd_t *in){
270 uint64_t exp_part, significand;
271 uint32_t status = 0;
272 size_t bases;
273 uint16_t *bases_data;
274 ud64 ret;
275 mpd_context_t ctx;
276
277 mpd_ieee_context(&ctx,MPD_DECIMAL64);
278 mpd_qfinalize(in, &ctx,&status);
279
280 exp_part = in->exp + (uint64_t)mpd_trail_zeros(in) + 398LL; /* rough guess? */
281 in->exp = 0;
282 bases = mpd_sizeinbase(in, UINT16_MAX+1);
283 bases_data = __mingw_dfp_get_globals()->mpd_callocfunc(bases < 4 ? 4 : bases,sizeof(uint16_t));
284 mpd_qexport_u16(bases_data,bases,UINT16_MAX+1,in,&status);
285 significand = bases_data[0] | (uint64_t)bases_data[1] << 16 | (uint64_t)bases_data[2] << 32 | (uint64_t)bases_data[3] << 48;
286 __mingw_dfp_get_globals()->mpd_free(bases_data);
287 ret.t0.sign = mpd_isnegative(in);
288 if((significand & (0x7ULL << 51)) == (0x1ULL << 53)) { /* 100 MSB? */
289 ret.t2.bits = 0x3;
290 ret.t2.mantissa = significand;
291 ret.t2.exponent = exp_part;
292 } else {
293 ret.t1.mantissa = significand;
294 ret.t1.exponent = exp_part;
295 }
296 return ret.d;
297 }
298
mpd_to_dec128(mpd_t * in)299 static _Decimal128 mpd_to_dec128(mpd_t *in){
300 uint64_t exp_part,significand[2];
301 uint16_t *bases_data;
302 ud128 ret;
303 mpd_context_t ctx;
304 size_t bases;
305 uint32_t status = 0;
306
307 mpd_ieee_context(&ctx,MPD_DECIMAL128);
308 mpd_qfinalize(in, &ctx,&status);
309 exp_part = in->exp + (uint64_t)mpd_trail_zeros(in) + 6176LL; /* rough guess? */
310 in->exp = 0;
311 bases = mpd_sizeinbase(in, UINT16_MAX+1);
312 bases_data = __mingw_dfp_get_globals()->mpd_callocfunc(bases < 8 ? 8 : bases,sizeof(uint16_t));
313 mpd_qexport_u16(bases_data,bases,UINT16_MAX+1,in,&status);
314 significand[0] = bases_data[0] | (uint64_t)bases_data[1] << 16 | (uint64_t)bases_data[2] << 32 | (uint64_t)bases_data[3] << 48;
315 significand[1] = bases_data[4] | (uint64_t)bases_data[5] << 16 | (uint64_t)bases_data[6] << 32 | (uint64_t)bases_data[7] << 48;
316 __mingw_dfp_get_globals()->mpd_free(bases_data);
317 ret.t0.sign = mpd_isnegative(in);
318 if((significand[1] & (0x7ULL << 57)) == (0x1ULL << 49)) { /* 100 MSB? */
319 ret.t2.bits = 0x3;
320 ret.t2.mantissaL = significand[0];
321 ret.t2.mantissaH = significand[1];
322 ret.t2.exponent = exp_part;
323 } else {
324 ret.t1.mantissaL = significand[0];
325 ret.t1.mantissaH = significand[1];
326 ret.t1.exponent = exp_part;
327 }
328 return ret.d;
329
330 }
331
main()332 int main(){
333 mpd_context_t ctx;
334 mpd_t *result1;
335 mpd_t *result2;
336 mpd_t *result3;
337 mpd_setminalloc(MPD_MINALLOC_MAX);
338 mpd_ieee_context(&ctx, 160);
339 result1 = mpd_qnew();
340 result2 = mpd_qnew();
341 result3 = mpd_qnew();
342 //mpd_qset_u64(result1,2ULL,&ctx,&status);
343 dec32_to_mpd(&ctx,result1,dec32);
344 dec64_to_mpd(&ctx,result2,dec64);
345 dec128_to_mpd(&ctx,result3,dec128);
346 //mpd_qset_u64(result2,4ULL,&ctx,&status);
347 //mpd_qpow(result3,result1,result2,&ctx,&status);
348 mpd_print(result1);
349 mpd_print(result2);
350 mpd_print(result3);
351
352 /*print_mpd(result1);
353 print_mpd(result2);
354 print_mpd(result3);*/
355
356 _Decimal32 ddd = mpd_to_dec32(result1);
357 printf ("Compare is %d\n", memcmp(&ddd,&dec32,sizeof(_Decimal32)));
358 printf ("0x%x\n0x%x\n", *((uint32_t *)(void *)&ddd), *((uint32_t *)(void *)&dec32));
359
360 _Decimal64 ddd64 = mpd_to_dec64(result2);
361 printf ("Compare is %d\n", memcmp(&ddd64,&dec64,sizeof(_Decimal64)));
362 printf ("0x%I64x\n0x%I64x\n", *((uint64_t *)(void *)&ddd64), *((uint64_t *)(void *)&dec64));
363
364 _Decimal128 ddd128 = mpd_to_dec128(result3);
365 printf ("Compare is %d\n", memcmp(&ddd128,&dec128,sizeof(_Decimal128)));
366 printf ("0x%I64d\n0x%I64x\n", *((uint64_t *)(void *)&ddd128), *((uint64_t *)(void *)&dec128));
367
368 mpd_del(result1);
369 mpd_del(result2);
370 mpd_del(result3);
371
372 print_dec32(&dec32);
373 print_dec64(&dec64);
374 print_dec128(&dec128);
375 return 0;
376 }
377