[BACK]Return to bf.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / engine

Annotation of OpenXM_contrib2/asir2000/engine/bf.c, Revision 1.10

1.2       noro        1: /*
1.10    ! noro        2:  * $OpenXM: OpenXM_contrib2/asir2000/engine/bf.c,v 1.9 2015/08/06 00:43:20 noro Exp $
1.7       noro        3:  */
1.1       noro        4: #include "ca.h"
                      5: #include "base.h"
                      6: #include <math.h>
                      7:
1.7       noro        8: Num tobf(Num,int);
1.1       noro        9:
1.7       noro       10: #define BFPREC(a) (((BF)(a))->body->_mpfr_prec)
                     11:
                     12: void strtobf(char *s,BF *p)
                     13: {
                     14:   BF r;
                     15:   NEWBF(r);
                     16:   mpfr_init(r->body);
                     17:   mpfr_set_str(r->body,s,10,MPFR_RNDN);
                     18:   *p = r;
                     19: }
                     20:
                     21: double mpfrtodbl(mpfr_t a)
                     22: {
                     23:   return mpfr_get_d(a,MPFR_RNDN);
                     24: }
                     25:
                     26: Num tobf(Num a,int prec)
                     27: {
                     28:   mpfr_t r;
                     29:   mpz_t z;
                     30:   mpq_t q;
                     31:   BF d;
                     32:   N nm,dn;
                     33:   int sgn;
                     34:
                     35:   if ( !a ) {
1.8       noro       36:     prec ? mpfr_init2(r,prec) : mpfr_init(r);
1.7       noro       37:     mpfr_set_zero(r,1);
                     38:     MPFRTOBF(r,d);
                     39:     return (Num)d;
                     40:   } else {
                     41:     switch ( NID(a) ) {
                     42:     case N_B:
                     43:       return a;
                     44:       break;
1.8       noro       45:     case N_R:
                     46:       prec ? mpfr_init2(r,prec) : mpfr_init(r);
                     47:       mpfr_init_set_d(r,((Real)a)->body,MPFR_RNDN);
1.7       noro       48:       MPFRTOBF(r,d);
                     49:       return (Num)d;
1.8       noro       50:       break;
1.7       noro       51:     case N_Q:
                     52:       nm = NM((Q)a); dn = DN((Q)a); sgn = SGN((Q)a);
                     53:       if ( INT((Q)a) ) {
                     54:         mpz_init(z);
                     55:         mpz_import(z,PL(nm),-1,sizeof(BD(nm)[0]),0,0,BD(nm));
                     56:         if ( sgn < 0 ) mpz_neg(z,z);
                     57:         mpfr_init_set_z(r,z,MPFR_RNDN);
                     58:       } else {
                     59:         mpq_init(q);
                     60:         mpz_import(mpq_numref(q),PL(nm),-1,sizeof(BD(nm)[0]),0,0,BD(nm));
                     61:         mpz_import(mpq_denref(q),PL(dn),-1,sizeof(BD(dn)[0]),0,0,BD(dn));
                     62:         if ( sgn < 0 ) mpq_neg(q,q);
                     63:         mpfr_init_set_q(r,q,MPFR_RNDN);
                     64:       }
                     65:       MPFRTOBF(r,d);
                     66:       return (Num)d;
                     67:       break;
                     68:     default:
                     69:       error("tobf : invalid argument");
1.8       noro       70:       break;
1.7       noro       71:     }
                     72:   }
                     73: }
                     74:
                     75: void addbf(Num a,Num b,Num *c)
                     76: {
                     77:   mpfr_t r;
                     78:   BF d;
1.8       noro       79:   GZ z;
                     80:   GQ q;
1.7       noro       81:
                     82:   if ( !a )
                     83:     *c = b;
                     84:   else if ( !b )
                     85:     *c = a;
                     86:   else if ( (NID(a) <= N_A) && (NID(b) <= N_A ) )
                     87:     (*addnumt[MIN(NID(a),NID(b))])(a,b,c);
1.9       noro       88:   else if ( NID(a) == N_B ) {
                     89:     switch ( NID(b) ) {
                     90:     case N_Q:
                     91:       mpfr_init2(r,BFPREC(a));
                     92:       if ( INT((Q)b) ) {
                     93:         z = ztogz((Q)b);
                     94:         mpfr_add_z(r,((BF)a)->body,z->body,MPFR_RNDN);
                     95:       } else {
                     96:         q = qtogq((Q)b);
                     97:         mpfr_add_q(r,((BF)a)->body,q->body,MPFR_RNDN);
                     98:       }
                     99:       break;
                    100:     case N_R:
                    101:       /* double precision = 53 */
                    102:       mpfr_init2(r,MAX(BFPREC(a),53));
                    103:       mpfr_add_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
                    104:       break;
                    105:     case N_B:
                    106:       mpfr_init2(r,MAX(BFPREC(a),BFPREC(b)));
                    107:       mpfr_add(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    108:       break;
                    109:     }
                    110:     MPFRTOBF(r,d);
                    111:     *c = (Num)d;
                    112:   } else { /* NID(b)==N_B */
                    113:     switch ( NID(a) ) {
                    114:     case N_Q:
                    115:       mpfr_init2(r,BFPREC(b));
                    116:       if ( INT((Q)a) ) {
                    117:         z = ztogz((Q)a);
                    118:         mpfr_add_z(r,((BF)b)->body,z->body,MPFR_RNDN);
                    119:       } else {
                    120:         q = qtogq((Q)a);
                    121:         mpfr_add_q(r,((BF)b)->body,q->body,MPFR_RNDN);
1.8       noro      122:       }
1.9       noro      123:       break;
                    124:     case N_R:
                    125:       /* double precision = 53 */
                    126:       mpfr_init2(r,MAX(BFPREC(b),53));
                    127:       mpfr_add_d(r,((BF)b)->body,((Real)a)->body,MPFR_RNDN);
                    128:       break;
1.8       noro      129:     }
1.7       noro      130:     MPFRTOBF(r,d);
                    131:     *c = (Num)d;
                    132:   }
                    133: }
                    134:
                    135: void subbf(Num a,Num b,Num *c)
                    136: {
1.8       noro      137:   mpfr_t r,s;
                    138:   GZ z;
                    139:   GQ q;
1.7       noro      140:   BF d;
                    141:
                    142:   if ( !a )
                    143:     (*chsgnnumt[NID(b)])(b,c);
                    144:   else if ( !b )
                    145:     *c = a;
                    146:   else if ( (NID(a) <= N_A) && (NID(b) <= N_A ) )
                    147:     (*subnumt[MIN(NID(a),NID(b))])(a,b,c);
1.9       noro      148:   else if ( NID(a) == N_B ) {
                    149:     switch ( NID(b) ) {
                    150:     case N_Q:
                    151:       mpfr_init2(r,BFPREC(a));
                    152:       if ( INT((Q)b) ) {
                    153:         z = ztogz((Q)b);
                    154:         mpfr_sub_z(r,((BF)a)->body,z->body,MPFR_RNDN);
                    155:       } else {
                    156:         q = qtogq((Q)b);
                    157:         mpfr_sub_q(r,((BF)a)->body,q->body,MPFR_RNDN);
                    158:       }
                    159:       break;
                    160:     case N_R:
                    161:       /* double precision = 53 */
                    162:       mpfr_init2(r,MAX(BFPREC(a),53));
                    163:       mpfr_sub_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
                    164:       break;
                    165:     case N_B:
                    166:       mpfr_init2(r,MAX(BFPREC(a),BFPREC(b)));
                    167:       mpfr_sub(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    168:       break;
                    169:     }
                    170:     MPFRTOBF(r,d);
                    171:     *c = (Num)d;
                    172:   } else { /* NID(b)==N_B */
                    173:     switch ( NID(a) ) {
                    174:     case N_Q:
                    175:       mpfr_init2(r,BFPREC(b));
                    176:       if ( INT((Q)a) ) {
                    177:         z = ztogz((Q)a);
1.10    ! noro      178:         mpfr_sub_z(r,((BF)b)->body,z->body,MPFR_RNDN);
1.9       noro      179:       } else {
                    180:         q = qtogq((Q)a);
1.10    ! noro      181:         mpfr_sub_q(r,((BF)b)->body,q->body,MPFR_RNDN);
1.8       noro      182:       }
1.10    ! noro      183:       mpfr_neg(r,r,MPFR_RNDN);
1.9       noro      184:       break;
                    185:     case N_R:
                    186:       /* double precision = 53 */
                    187:       mpfr_init2(r,MAX(BFPREC(b),53));
                    188:       mpfr_d_sub(r,((Real)a)->body,((BF)b)->body,MPFR_RNDN);
                    189:       break;
1.8       noro      190:     }
1.7       noro      191:     MPFRTOBF(r,d);
                    192:     *c = (Num)d;
                    193:   }
                    194: }
                    195:
                    196: void mulbf(Num a,Num b,Num *c)
                    197: {
                    198:   mpfr_t r;
1.8       noro      199:   GZ z;
                    200:   GQ q;
1.7       noro      201:   BF d;
                    202:   int prec;
                    203:
                    204:   if ( !a || !b )
                    205:     *c = 0;
                    206:   else if ( (NID(a) <= N_A) && (NID(b) <= N_A ) )
                    207:     (*mulnumt[MIN(NID(a),NID(b))])(a,b,c);
1.9       noro      208:   else if ( NID(a) == N_B ) {
                    209:     switch ( NID(b) ) {
                    210:     case N_Q:
                    211:       mpfr_init2(r,BFPREC(a));
                    212:       if ( INT((Q)b) ) {
                    213:         z = ztogz((Q)b);
                    214:         mpfr_mul_z(r,((BF)a)->body,z->body,MPFR_RNDN);
                    215:       } else {
                    216:         q = qtogq((Q)b);
                    217:         mpfr_mul_q(r,((BF)a)->body,q->body,MPFR_RNDN);
                    218:       }
                    219:       break;
                    220:     case N_R:
                    221:       /* double precision = 53 */
                    222:       mpfr_init2(r,MAX(BFPREC(a),53));
                    223:       mpfr_mul_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
                    224:       break;
                    225:     case N_B:
                    226:       mpfr_init2(r,MAX(BFPREC(a),BFPREC(b)));
                    227:       mpfr_mul(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    228:       break;
                    229:     }
                    230:     MPFRTOBF(r,d);
                    231:     *c = (Num)d;
                    232:   } else { /* NID(b)==N_B */
                    233:     switch ( NID(a) ) {
                    234:     case N_Q:
                    235:       mpfr_init2(r,BFPREC(b));
                    236:       if ( INT((Q)a) ) {
                    237:         z = ztogz((Q)a);
                    238:         mpfr_mul_z(r,((BF)b)->body,z->body,MPFR_RNDN);
                    239:       } else {
                    240:         q = qtogq((Q)a);
                    241:         mpfr_mul_q(r,((BF)b)->body,q->body,MPFR_RNDN);
1.8       noro      242:       }
1.9       noro      243:       break;
                    244:     case N_R:
                    245:       /* double precision = 53 */
                    246:       mpfr_init2(r,MAX(BFPREC(b),53));
                    247:       mpfr_mul_d(r,((BF)b)->body,((Real)a)->body,MPFR_RNDN);
                    248:       break;
1.8       noro      249:     }
1.7       noro      250:     MPFRTOBF(r,d);
                    251:     *c = (Num)d;
                    252:   }
                    253: }
                    254:
                    255: void divbf(Num a,Num b,Num *c)
                    256: {
1.8       noro      257:   mpfr_t s,r;
                    258:   GZ z;
                    259:   GQ q;
1.7       noro      260:   BF d;
                    261:
                    262:   if ( !b )
                    263:     error("divbf : division by 0");
                    264:   else if ( !a )
                    265:     *c = 0;
                    266:   else if ( (NID(a) <= N_A) && (NID(b) <= N_A ) )
                    267:     (*divnumt[MIN(NID(a),NID(b))])(a,b,c);
1.9       noro      268:   else if ( NID(a) == N_B ) {
                    269:     switch ( NID(b) ) {
                    270:     case N_Q:
                    271:       mpfr_init2(r,BFPREC(a));
                    272:       if ( INT((Q)b) ) {
                    273:         z = ztogz((Q)b);
                    274:         mpfr_div_z(r,((BF)a)->body,z->body,MPFR_RNDN);
                    275:       } else {
                    276:         q = qtogq((Q)b);
                    277:         mpfr_div_q(r,((BF)a)->body,q->body,MPFR_RNDN);
1.8       noro      278:       }
1.9       noro      279:       break;
                    280:     case N_R:
                    281:       /* double precision = 53 */
                    282:       mpfr_init2(r,MAX(BFPREC(a),53));
                    283:       mpfr_div_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
                    284:       break;
                    285:     case N_B:
                    286:       mpfr_init2(r,MAX(BFPREC(a),BFPREC(b)));
                    287:       mpfr_div(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    288:       break;
                    289:     }
                    290:     MPFRTOBF(r,d);
                    291:     *c = (Num)d;
                    292:   } else { /* NID(b)==N_B */
                    293:     switch ( NID(a) ) {
                    294:     case N_Q:
                    295:       /* XXX : mpfr_z_div and mpfr_q_div are not implemented */
                    296:       a = tobf(a,BFPREC(b));
                    297:       mpfr_init2(r,BFPREC(b));
                    298:       mpfr_div(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    299:       break;
                    300:     case N_R:
                    301:       /* double precision = 53 */
                    302:       mpfr_init2(r,MAX(BFPREC(b),53));
                    303:       mpfr_d_div(r,((Real)a)->body,((BF)b)->body,MPFR_RNDN);
                    304:       break;
1.8       noro      305:     }
1.7       noro      306:     MPFRTOBF(r,d);
                    307:     *c = (Num)d;
                    308:   }
                    309: }
                    310:
                    311: void pwrbf(Num a,Num b,Num *c)
                    312: {
1.8       noro      313:   int prec;
1.7       noro      314:   mpfr_t r;
1.8       noro      315:   GZ z;
1.7       noro      316:   BF d;
                    317:
                    318:   if ( !b )
                    319:     *c = (Num)ONE;
                    320:   else if ( !a )
                    321:     *c = 0;
                    322:   else if ( (NID(a) <= N_A) && (NID(b) <= N_A ) )
                    323:     (*pwrnumt[MIN(NID(a),NID(b))])(a,b,c);
1.9       noro      324:   else if ( NID(a) == N_B ) {
                    325:     switch ( NID(b) ) {
                    326:     case N_Q:
                    327:       mpfr_init2(r,BFPREC(a));
                    328:       if ( INT((Q)b) ) {
                    329:         z = ztogz((Q)b);
                    330:         mpfr_pow_z(r,((BF)a)->body,z->body,MPFR_RNDN);
                    331:       } else {
                    332:         b = tobf(b,BFPREC(a));
1.8       noro      333:         mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    334:       }
1.9       noro      335:       break;
                    336:     case N_R:
                    337:       /* double precision = 53 */
                    338:       prec = MAX(BFPREC(a),53);
                    339:       mpfr_init2(r,prec);
                    340:       b = tobf(b,prec);
                    341:       mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    342:       break;
                    343:     case N_B:
                    344:       mpfr_init2(r,MAX(BFPREC(a),BFPREC(b)));
                    345:       mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    346:       break;
                    347:     }
                    348:     MPFRTOBF(r,d);
                    349:     *c = (Num)d;
                    350:   } else { /* NID(b)==N_B */
                    351:     switch ( NID(a) ) {
                    352:     case N_Q:
                    353:       mpfr_init2(r,BFPREC(b));
                    354:       a = tobf(a,BFPREC(b));
                    355:       mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    356:       break;
                    357:     case N_R:
                    358:       /* double precision = 53 */
                    359:       prec = MAX(BFPREC(a),53);
                    360:       mpfr_init2(r,prec);
                    361:       a = tobf(a,prec);
                    362:       mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    363:       break;
1.8       noro      364:     }
1.7       noro      365:     MPFRTOBF(r,d);
                    366:     *c = (Num)d;
                    367:   }
                    368: }
                    369:
                    370: void chsgnbf(Num a,Num *c)
                    371: {
                    372:   mpfr_t r;
                    373:   BF d;
                    374:
                    375:   if ( !a )
                    376:     *c = 0;
                    377:   else if ( NID(a) <= N_A )
                    378:     (*chsgnnumt[NID(a)])(a,c);
                    379:   else {
                    380:     mpfr_init2(r,BFPREC(a));
                    381:     mpfr_neg(r,((BF)a)->body,MPFR_RNDN);
                    382:     MPFRTOBF(r,d);
                    383:     *c = (Num)d;
                    384:   }
                    385: }
                    386:
                    387: int cmpbf(Num a,Num b)
                    388: {
1.9       noro      389:   int ret;
                    390:   GZ z;
                    391:   GQ q;
                    392:
1.7       noro      393:   if ( !a ) {
                    394:     if ( !b || (NID(b)<=N_A) )
                    395:       return (*cmpnumt[NID(b)])(a,b);
                    396:     else
                    397:       return -mpfr_sgn(((BF)a)->body);
                    398:   } else if ( !b ) {
                    399:     if ( !a || (NID(a)<=N_A) )
                    400:       return (*cmpnumt[NID(a)])(a,b);
                    401:     else
                    402:       return mpfr_sgn(((BF)a)->body);
1.9       noro      403:   } else if ( NID(a) == N_B ) {
                    404:     switch ( NID(b) ) {
                    405:     case N_Q:
                    406:       if ( INT((Q)b) ) {
                    407:         z = ztogz((Q)b);
                    408:         ret = mpfr_cmp_z(((BF)a)->body,z->body);
                    409:       } else {
                    410:         q = qtogq((Q)b);
                    411:         ret = mpfr_cmp_q(((BF)a)->body,q->body);
                    412:       }
                    413:       break;
                    414:     case N_R:
                    415:       /* double precision = 53 */
                    416:       ret = mpfr_cmp_d(((BF)a)->body,((Real)b)->body);
                    417:       break;
                    418:     case N_B:
                    419:       ret = mpfr_cmp(((BF)a)->body,((BF)b)->body);
                    420:       break;
                    421:     }
                    422:     return ret;
                    423:   } else { /* NID(b)==N_B */
                    424:     switch ( NID(a) ) {
                    425:     case N_Q:
                    426:       if ( INT((Q)a) ) {
                    427:         z = ztogz((Q)a);
                    428:         ret = mpfr_cmp_z(((BF)b)->body,z->body);
                    429:       } else {
                    430:         q = qtogq((Q)a);
                    431:         ret = mpfr_cmp_q(((BF)b)->body,q->body);
                    432:       }
                    433:       break;
                    434:     case N_R:
                    435:       /* double precision = 53 */
                    436:       ret = mpfr_cmp_d(((BF)b)->body,((Real)a)->body);
                    437:       break;
                    438:     }
                    439:     return -ret;
1.7       noro      440:   }
1.1       noro      441: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>