[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.14

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

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