| /* |
| This Software is provided under the Zope Public License (ZPL) Version 2.1. |
| |
| Copyright (c) 2009 - 2013 by the mingw-w64 project |
| |
| See the AUTHORS file for the list of contributors to the mingw-w64 project. |
| |
| This license has been certified as open source. It has also been designated |
| as GPL compatible by the Free Software Foundation (FSF). |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are met: |
| |
| 1. Redistributions in source code must retain the accompanying copyright |
| notice, this list of conditions, and the following disclaimer. |
| 2. Redistributions in binary form must reproduce the accompanying |
| copyright notice, this list of conditions, and the following disclaimer |
| in the documentation and/or other materials provided with the |
| distribution. |
| 3. Names of the copyright holders must not be used to endorse or promote |
| products derived from this software without prior written permission |
| from the copyright holders. |
| 4. The right to distribute this software or to use it for any purpose does |
| not give you the right to use Servicemarks (sm) or Trademarks (tm) of |
| the copyright holders. Use of them is covered by separate agreement |
| with the copyright holders. |
| 5. If any files are modified, you must cause the modified files to carry |
| prominent notices stating that you changed the files and the date of |
| any change. |
| |
| Disclaimer |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED |
| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, |
| OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * Prelim Encoder/Decoder Test |
| * Build with -std=gnu99 -Wall -Wextra -Wformat -Wstrict-aliasing -Wshadow -Wpacked \ |
| * -Winline -Wimplicit-function-declaration -Wmissing-noreturn -Wmissing-prototypes \ |
| * -g -O2 -m32 -std=gnu99 -frounding-math -fsignaling-nans -Wno-inline -DCONFIG_32 \ |
| * -DPPRO -DASM -Dmpdecimal_header=\"mpdecimal-i686.h\" -fno-strict-aliasing \ |
| * -Wno-unused-function |
| */ |
| |
| #include <stdio.h> |
| #include <inttypes.h> |
| #include "dfp_internal.h" |
| #include mpdecimal_header |
| |
| static const _Decimal32 dec32 = 0.0DF; |
| static const _Decimal64 dec64 = 0.0DD; |
| static const _Decimal128 dec128 = 0.0DL; |
| |
| static void print_mpd(const mpd_t *in){ |
| printf("----\n"); |
| printf("flags: %d\n",in->flags); |
| printf("exp: %I64d\n",(uint64_t)in->exp); |
| printf("digits: %I64d\n",(uint64_t)in->digits); |
| printf("trail: %I64d\n",(uint64_t)mpd_trail_zeros(in)); |
| printf("len: %I64d\n",(uint64_t)in->len); |
| printf("alloc: %I64d\n",(uint64_t)in->alloc); |
| printf("data: "); |
| for(mpd_ssize_t i = 0; i < in->len; i++){ |
| printf("[%09I64x]",(uint64_t)in->data[i]); |
| } |
| printf("\n"); |
| printf("----\n"); |
| } |
| |
| static void print_dec32(const _Decimal32 *in){ |
| ud32 ret; |
| ret.d = *in; |
| printf("----\n"); |
| printf("sign %x\n", ret.t0.sign); |
| printf("bits %x\n", ret.t0.bits); |
| printf("flag %x\n", ret.t0.flag); |
| if(ret.t0.bits == 0x3){ |
| printf("exp %d\n", ret.t2.exponent); |
| printf("mantissa %d\n", ret.t2.mantissa); |
| } else { |
| printf("exp %d\n", ret.t1.exponent); |
| printf("mantissa %d\n", ret.t1.mantissa); |
| } |
| printf("----\n"); |
| } |
| |
| static void print_dec64(const _Decimal64 *in){ |
| ud64 ret; |
| ret.d = *in; |
| printf("----\n"); |
| printf("sign %x\n", ret.t0.sign); |
| printf("bits %x\n", ret.t0.bits); |
| printf("flag %x\n", ret.t0.flag); |
| if(ret.t0.bits == 0x3){ |
| printf("exp %d\n", ret.t2.exponent); |
| printf("mantissa %I64u\n", (uint64_t)ret.t2.mantissa); |
| } else { |
| printf("exp %d\n", ret.t1.exponent); |
| printf("mantissa %I64u\n", (uint64_t)ret.t1.mantissa); |
| } |
| printf("----\n"); |
| } |
| |
| static void print_dec128(const _Decimal128 *in){ |
| ud128 ret; |
| ret.d = *in; |
| printf("----\n"); |
| printf("sign %x\n", ret.t0.sign); |
| printf("bits %x\n", ret.t0.bits); |
| printf("flag %x\n", ret.t0.flag); |
| if(ret.t0.bits == 0x3){ |
| printf("exp %d\n", ret.t2.exponent); |
| printf("mantissaL %I64u\n", (uint64_t)ret.t2.mantissaL); |
| printf("mantissaH %I64u\n", (uint64_t)ret.t2.mantissaH); |
| } else { |
| printf("exp %d\n", ret.t1.exponent); |
| printf("mantissaL %I64u\n", (uint64_t)ret.t1.mantissaL); |
| printf("mantissaH %I64u\n", (uint64_t)ret.t1.mantissaH); |
| } |
| printf("----\n"); |
| } |
| |
| |
| static void dec_to_mpd_conv(mpd_context_t * ctx, mpd_t *result, const int64_t significand_low, const int64_t exponent_part){ |
| uint32_t status = 0; |
| mpd_t *ten, *exp_pow, *exp_partmpd, *significand_partmpd; |
| ten = mpd_qnew(); |
| exp_pow = mpd_qnew(); |
| exp_partmpd = mpd_qnew(); |
| significand_partmpd = mpd_qnew(); |
| |
| mpd_qset_i64(ten,10LL,ctx,&status); |
| mpd_qset_i64(significand_partmpd,significand_low,ctx,&status); |
| mpd_qset_i64(exp_partmpd,exponent_part,ctx,&status); |
| mpd_qpow(exp_pow,ten,exp_partmpd,ctx,&status); |
| mpd_qmul(result,significand_partmpd,exp_pow,ctx,&status); |
| |
| mpd_del(ten); |
| mpd_del(exp_pow); |
| mpd_del(exp_partmpd); |
| mpd_del(significand_partmpd); |
| } |
| |
| 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){ |
| uint32_t status = 0; |
| mpd_t *ten, *sig1, *sig2, *stemp, *sig, *s64, *exp_pow, *exp_partmpd; |
| ten = mpd_qnew(); |
| s64 = mpd_qnew(); |
| sig1 = mpd_qnew(); |
| sig2 = mpd_qnew(); |
| stemp = mpd_qnew(); |
| sig = mpd_qnew(); |
| exp_pow = mpd_qnew(); |
| exp_partmpd = mpd_qnew(); |
| mpd_qset_i64(ten,10LL,ctx,&status); |
| /* 2^64 */ |
| mpd_qset_string(s64,"18446744073709551616",ctx,&status); |
| mpd_qset_u64(sig1,significand_low,ctx,&status); |
| mpd_qset_i64(sig2,significand_high,ctx,&status); |
| mpd_qmul(stemp,sig2,s64,ctx,&status); |
| mpd_qadd(sig,stemp,sig1,ctx,&status); |
| mpd_qset_i64(exp_partmpd,exponent_part,ctx,&status); |
| mpd_qpow(exp_pow,ten,exp_partmpd,ctx,&status); |
| mpd_qmul(result,sig,exp_pow,ctx,&status); |
| mpd_del(ten); |
| mpd_del(sig1); |
| mpd_del(sig2); |
| mpd_del(sig); |
| mpd_del(stemp); |
| mpd_del(s64); |
| mpd_del(exp_pow); |
| mpd_del(exp_partmpd); |
| } |
| |
| static uint32_t dec128_to_mpd(mpd_context_t * ctx, mpd_t *result, const _Decimal128 deci){ |
| int64_t significand2, exp_part; |
| uint64_t significand1; |
| ud128 in = {.d = deci}; |
| |
| if(in.t0.bits == 0x3){ /*case 11 */ |
| /* should not enter here */ |
| exp_part = in.t2.exponent; |
| significand1 = in.t2.mantissaL; |
| significand2 = (in.t2.mantissaH | (0x1ULL << 49)) * ((in.t2.sign) ? -1 : 1); |
| } else { |
| exp_part = in.t1.exponent; |
| significand1 = in.t1.mantissaL; |
| significand2 = in.t1.mantissaH * ((in.t1.sign) ? -1 : 1); |
| } |
| |
| printf("%I64d %I64d\n", significand1, significand2); |
| |
| exp_part -= 6176; /* exp bias */ |
| dec128_to_mpd_conv(ctx, result, significand1, significand2, exp_part); |
| return 0; |
| } |
| |
| static uint32_t dec64_to_mpd(mpd_context_t * ctx, mpd_t *result, const _Decimal64 deci){ |
| int64_t significand, exp_part; |
| ud64 in = {.d = deci}; |
| |
| if(in.t0.bits == 0x3){ /*case 11 */ |
| exp_part = in.t2.exponent; |
| significand = (in.t2.mantissa | (0x1ULL << 53)) * ((in.t2.sign) ? -1 : 1); |
| } else { |
| exp_part = in.t1.exponent; |
| significand = in.t1.mantissa * ((in.t1.sign) ? -1 : 1); |
| } |
| exp_part -= 398; /* exp bias */ |
| dec_to_mpd_conv(ctx, result, significand, exp_part); |
| return 0; |
| } |
| |
| static uint32_t dec32_to_mpd(mpd_context_t * ctx, mpd_t *result, const _Decimal32 deci){ |
| int64_t significand, exp_part; |
| ud32 in = {.d = deci}; |
| |
| if(in.t0.bits == 0x3){ /*case 11 */ |
| exp_part = in.t2.exponent; |
| significand = (in.t2.mantissa | (0x1ULL << 23)) * ((in.t2.sign) ? -1 : 1); |
| } else { |
| exp_part = in.t1.exponent; |
| significand = in.t1.mantissa * ((in.t1.sign) ? -1 : 1); |
| } |
| exp_part -= 101; /* exp bias */ |
| dec_to_mpd_conv(ctx, result, significand, exp_part); |
| return 0; |
| } |
| |
| static _Decimal32 mpd_to_dec32(mpd_t *in){ |
| uint32_t exp_part, significand; |
| uint32_t status = 0; |
| ud32 ret; |
| mpd_context_t ctx; |
| uint16_t *bases_data; |
| size_t bases; |
| |
| mpd_ieee_context(&ctx,MPD_DECIMAL32); |
| mpd_qfinalize(in, &ctx,&status); |
| |
| exp_part = in->exp + (uint32_t)mpd_trail_zeros(in) + 101LL; /* rough guess? */ |
| in->exp = 0; |
| bases = mpd_sizeinbase(in, UINT16_MAX+1); |
| bases_data = __mingw_dfp_get_globals()->mpd_callocfunc(bases < 2 ? 2 : bases,sizeof(uint16_t)); |
| mpd_qexport_u16(bases_data,bases,UINT16_MAX+1,in,&status); |
| significand = bases_data[0] | (uint32_t)bases_data[1] << 16 ; |
| __mingw_dfp_get_globals()->mpd_free(bases_data); |
| ret.t0.sign = mpd_isnegative(in); |
| if((significand & (0x7ULL << 21)) == (0x1ULL << 23)) { /* 100 MSB? */ |
| ret.t2.bits = 0x3; |
| ret.t2.mantissa = significand; |
| ret.t2.exponent = exp_part; |
| } else { |
| ret.t1.mantissa = significand; |
| ret.t1.exponent = exp_part; |
| } |
| return ret.d; |
| } |
| |
| static _Decimal64 mpd_to_dec64(mpd_t *in){ |
| uint64_t exp_part, significand; |
| uint32_t status = 0; |
| size_t bases; |
| uint16_t *bases_data; |
| ud64 ret; |
| mpd_context_t ctx; |
| |
| mpd_ieee_context(&ctx,MPD_DECIMAL64); |
| mpd_qfinalize(in, &ctx,&status); |
| |
| exp_part = in->exp + (uint64_t)mpd_trail_zeros(in) + 398LL; /* rough guess? */ |
| in->exp = 0; |
| bases = mpd_sizeinbase(in, UINT16_MAX+1); |
| bases_data = __mingw_dfp_get_globals()->mpd_callocfunc(bases < 4 ? 4 : bases,sizeof(uint16_t)); |
| mpd_qexport_u16(bases_data,bases,UINT16_MAX+1,in,&status); |
| significand = bases_data[0] | (uint64_t)bases_data[1] << 16 | (uint64_t)bases_data[2] << 32 | (uint64_t)bases_data[3] << 48; |
| __mingw_dfp_get_globals()->mpd_free(bases_data); |
| ret.t0.sign = mpd_isnegative(in); |
| if((significand & (0x7ULL << 51)) == (0x1ULL << 53)) { /* 100 MSB? */ |
| ret.t2.bits = 0x3; |
| ret.t2.mantissa = significand; |
| ret.t2.exponent = exp_part; |
| } else { |
| ret.t1.mantissa = significand; |
| ret.t1.exponent = exp_part; |
| } |
| return ret.d; |
| } |
| |
| static _Decimal128 mpd_to_dec128(mpd_t *in){ |
| uint64_t exp_part,significand[2]; |
| uint16_t *bases_data; |
| ud128 ret; |
| mpd_context_t ctx; |
| size_t bases; |
| uint32_t status = 0; |
| |
| mpd_ieee_context(&ctx,MPD_DECIMAL128); |
| mpd_qfinalize(in, &ctx,&status); |
| exp_part = in->exp + (uint64_t)mpd_trail_zeros(in) + 6176LL; /* rough guess? */ |
| in->exp = 0; |
| bases = mpd_sizeinbase(in, UINT16_MAX+1); |
| bases_data = __mingw_dfp_get_globals()->mpd_callocfunc(bases < 8 ? 8 : bases,sizeof(uint16_t)); |
| mpd_qexport_u16(bases_data,bases,UINT16_MAX+1,in,&status); |
| significand[0] = bases_data[0] | (uint64_t)bases_data[1] << 16 | (uint64_t)bases_data[2] << 32 | (uint64_t)bases_data[3] << 48; |
| significand[1] = bases_data[4] | (uint64_t)bases_data[5] << 16 | (uint64_t)bases_data[6] << 32 | (uint64_t)bases_data[7] << 48; |
| __mingw_dfp_get_globals()->mpd_free(bases_data); |
| ret.t0.sign = mpd_isnegative(in); |
| if((significand[1] & (0x7ULL << 57)) == (0x1ULL << 49)) { /* 100 MSB? */ |
| ret.t2.bits = 0x3; |
| ret.t2.mantissaL = significand[0]; |
| ret.t2.mantissaH = significand[1]; |
| ret.t2.exponent = exp_part; |
| } else { |
| ret.t1.mantissaL = significand[0]; |
| ret.t1.mantissaH = significand[1]; |
| ret.t1.exponent = exp_part; |
| } |
| return ret.d; |
| |
| } |
| |
| int main(){ |
| mpd_context_t ctx; |
| mpd_t *result1; |
| mpd_t *result2; |
| mpd_t *result3; |
| mpd_setminalloc(MPD_MINALLOC_MAX); |
| mpd_ieee_context(&ctx, 160); |
| result1 = mpd_qnew(); |
| result2 = mpd_qnew(); |
| result3 = mpd_qnew(); |
| //mpd_qset_u64(result1,2ULL,&ctx,&status); |
| dec32_to_mpd(&ctx,result1,dec32); |
| dec64_to_mpd(&ctx,result2,dec64); |
| dec128_to_mpd(&ctx,result3,dec128); |
| //mpd_qset_u64(result2,4ULL,&ctx,&status); |
| //mpd_qpow(result3,result1,result2,&ctx,&status); |
| mpd_print(result1); |
| mpd_print(result2); |
| mpd_print(result3); |
| |
| /*print_mpd(result1); |
| print_mpd(result2); |
| print_mpd(result3);*/ |
| |
| _Decimal32 ddd = mpd_to_dec32(result1); |
| printf ("Compare is %d\n", memcmp(&ddd,&dec32,sizeof(_Decimal32))); |
| printf ("0x%x\n0x%x\n", *((uint32_t *)(void *)&ddd), *((uint32_t *)(void *)&dec32)); |
| |
| _Decimal64 ddd64 = mpd_to_dec64(result2); |
| printf ("Compare is %d\n", memcmp(&ddd64,&dec64,sizeof(_Decimal64))); |
| printf ("0x%I64x\n0x%I64x\n", *((uint64_t *)(void *)&ddd64), *((uint64_t *)(void *)&dec64)); |
| |
| _Decimal128 ddd128 = mpd_to_dec128(result3); |
| printf ("Compare is %d\n", memcmp(&ddd128,&dec128,sizeof(_Decimal128))); |
| printf ("0x%I64d\n0x%I64x\n", *((uint64_t *)(void *)&ddd128), *((uint64_t *)(void *)&dec128)); |
| |
| mpd_del(result1); |
| mpd_del(result2); |
| mpd_del(result3); |
| |
| print_dec32(&dec32); |
| print_dec64(&dec64); |
| print_dec128(&dec128); |
| return 0; |
| } |