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

1.2       noro        1: /*
1.9     ! noro        2:  * $OpenXM: OpenXM_contrib2/asir2000/engine/bf.c,v 1.8 2015/08/05 03:46:35 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(s,BFPREC(b));
        !           176:       mpfr_init2(r,BFPREC(b));
        !           177:       if ( INT((Q)a) ) {
        !           178:         z = ztogz((Q)a);
        !           179:         mpfr_sub_z(s,((BF)b)->body,z->body,MPFR_RNDN);
        !           180:       } else {
        !           181:         q = qtogq((Q)a);
        !           182:         mpfr_sub_q(s,((BF)b)->body,q->body,MPFR_RNDN);
1.8       noro      183:       }
1.9     ! noro      184:       mpfr_neg(r,s,MPFR_RNDN);
        !           185:       break;
        !           186:     case N_R:
        !           187:       /* double precision = 53 */
        !           188:       mpfr_init2(r,MAX(BFPREC(b),53));
        !           189:       mpfr_d_sub(r,((Real)a)->body,((BF)b)->body,MPFR_RNDN);
        !           190:       break;
1.8       noro      191:     }
1.7       noro      192:     MPFRTOBF(r,d);
                    193:     *c = (Num)d;
                    194:   }
                    195: }
                    196:
                    197: void mulbf(Num a,Num b,Num *c)
                    198: {
                    199:   mpfr_t r;
1.8       noro      200:   GZ z;
                    201:   GQ q;
1.7       noro      202:   BF d;
                    203:   int prec;
                    204:
                    205:   if ( !a || !b )
                    206:     *c = 0;
                    207:   else if ( (NID(a) <= N_A) && (NID(b) <= N_A ) )
                    208:     (*mulnumt[MIN(NID(a),NID(b))])(a,b,c);
1.9     ! noro      209:   else if ( NID(a) == N_B ) {
        !           210:     switch ( NID(b) ) {
        !           211:     case N_Q:
        !           212:       mpfr_init2(r,BFPREC(a));
        !           213:       if ( INT((Q)b) ) {
        !           214:         z = ztogz((Q)b);
        !           215:         mpfr_mul_z(r,((BF)a)->body,z->body,MPFR_RNDN);
        !           216:       } else {
        !           217:         q = qtogq((Q)b);
        !           218:         mpfr_mul_q(r,((BF)a)->body,q->body,MPFR_RNDN);
        !           219:       }
        !           220:       break;
        !           221:     case N_R:
        !           222:       /* double precision = 53 */
        !           223:       mpfr_init2(r,MAX(BFPREC(a),53));
        !           224:       mpfr_mul_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
        !           225:       break;
        !           226:     case N_B:
        !           227:       mpfr_init2(r,MAX(BFPREC(a),BFPREC(b)));
        !           228:       mpfr_mul(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           229:       break;
        !           230:     }
        !           231:     MPFRTOBF(r,d);
        !           232:     *c = (Num)d;
        !           233:   } else { /* NID(b)==N_B */
        !           234:     switch ( NID(a) ) {
        !           235:     case N_Q:
        !           236:       mpfr_init2(r,BFPREC(b));
        !           237:       if ( INT((Q)a) ) {
        !           238:         z = ztogz((Q)a);
        !           239:         mpfr_mul_z(r,((BF)b)->body,z->body,MPFR_RNDN);
        !           240:       } else {
        !           241:         q = qtogq((Q)a);
        !           242:         mpfr_mul_q(r,((BF)b)->body,q->body,MPFR_RNDN);
1.8       noro      243:       }
1.9     ! noro      244:       break;
        !           245:     case N_R:
        !           246:       /* double precision = 53 */
        !           247:       mpfr_init2(r,MAX(BFPREC(b),53));
        !           248:       mpfr_mul_d(r,((BF)b)->body,((Real)a)->body,MPFR_RNDN);
        !           249:       break;
1.8       noro      250:     }
1.7       noro      251:     MPFRTOBF(r,d);
                    252:     *c = (Num)d;
                    253:   }
                    254: }
                    255:
                    256: void divbf(Num a,Num b,Num *c)
                    257: {
1.8       noro      258:   mpfr_t s,r;
                    259:   GZ z;
                    260:   GQ q;
1.7       noro      261:   BF d;
                    262:
                    263:   if ( !b )
                    264:     error("divbf : division by 0");
                    265:   else if ( !a )
                    266:     *c = 0;
                    267:   else if ( (NID(a) <= N_A) && (NID(b) <= N_A ) )
                    268:     (*divnumt[MIN(NID(a),NID(b))])(a,b,c);
1.9     ! noro      269:   else if ( NID(a) == N_B ) {
        !           270:     switch ( NID(b) ) {
        !           271:     case N_Q:
        !           272:       mpfr_init2(r,BFPREC(a));
        !           273:       if ( INT((Q)b) ) {
        !           274:         z = ztogz((Q)b);
        !           275:         mpfr_div_z(r,((BF)a)->body,z->body,MPFR_RNDN);
        !           276:       } else {
        !           277:         q = qtogq((Q)b);
        !           278:         mpfr_div_q(r,((BF)a)->body,q->body,MPFR_RNDN);
1.8       noro      279:       }
1.9     ! noro      280:       break;
        !           281:     case N_R:
        !           282:       /* double precision = 53 */
        !           283:       mpfr_init2(r,MAX(BFPREC(a),53));
        !           284:       mpfr_div_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
        !           285:       break;
        !           286:     case N_B:
        !           287:       mpfr_init2(r,MAX(BFPREC(a),BFPREC(b)));
        !           288:       mpfr_div(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           289:       break;
        !           290:     }
        !           291:     MPFRTOBF(r,d);
        !           292:     *c = (Num)d;
        !           293:   } else { /* NID(b)==N_B */
        !           294:     switch ( NID(a) ) {
        !           295:     case N_Q:
        !           296:       /* XXX : mpfr_z_div and mpfr_q_div are not implemented */
        !           297:       a = tobf(a,BFPREC(b));
        !           298:       mpfr_init2(r,BFPREC(b));
        !           299:       mpfr_div(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           300:       break;
        !           301:     case N_R:
        !           302:       /* double precision = 53 */
        !           303:       mpfr_init2(r,MAX(BFPREC(b),53));
        !           304:       mpfr_d_div(r,((Real)a)->body,((BF)b)->body,MPFR_RNDN);
        !           305:       break;
1.8       noro      306:     }
1.7       noro      307:     MPFRTOBF(r,d);
                    308:     *c = (Num)d;
                    309:   }
                    310: }
                    311:
                    312: void pwrbf(Num a,Num b,Num *c)
                    313: {
1.8       noro      314:   int prec;
1.7       noro      315:   mpfr_t r;
1.8       noro      316:   GZ z;
1.7       noro      317:   BF d;
                    318:
                    319:   if ( !b )
                    320:     *c = (Num)ONE;
                    321:   else if ( !a )
                    322:     *c = 0;
                    323:   else if ( (NID(a) <= N_A) && (NID(b) <= N_A ) )
                    324:     (*pwrnumt[MIN(NID(a),NID(b))])(a,b,c);
1.9     ! noro      325:   else if ( NID(a) == N_B ) {
        !           326:     switch ( NID(b) ) {
        !           327:     case N_Q:
        !           328:       mpfr_init2(r,BFPREC(a));
        !           329:       if ( INT((Q)b) ) {
        !           330:         z = ztogz((Q)b);
        !           331:         mpfr_pow_z(r,((BF)a)->body,z->body,MPFR_RNDN);
        !           332:       } else {
        !           333:         b = tobf(b,BFPREC(a));
1.8       noro      334:         mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
                    335:       }
1.9     ! noro      336:       break;
        !           337:     case N_R:
        !           338:       /* double precision = 53 */
        !           339:       prec = MAX(BFPREC(a),53);
        !           340:       mpfr_init2(r,prec);
        !           341:       b = tobf(b,prec);
        !           342:       mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           343:       break;
        !           344:     case N_B:
        !           345:       mpfr_init2(r,MAX(BFPREC(a),BFPREC(b)));
        !           346:       mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           347:       break;
        !           348:     }
        !           349:     MPFRTOBF(r,d);
        !           350:     *c = (Num)d;
        !           351:   } else { /* NID(b)==N_B */
        !           352:     switch ( NID(a) ) {
        !           353:     case N_Q:
        !           354:       mpfr_init2(r,BFPREC(b));
        !           355:       a = tobf(a,BFPREC(b));
        !           356:       mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           357:       break;
        !           358:     case N_R:
        !           359:       /* double precision = 53 */
        !           360:       prec = MAX(BFPREC(a),53);
        !           361:       mpfr_init2(r,prec);
        !           362:       a = tobf(a,prec);
        !           363:       mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           364:       break;
1.8       noro      365:     }
1.7       noro      366:     MPFRTOBF(r,d);
                    367:     *c = (Num)d;
                    368:   }
                    369: }
                    370:
                    371: void chsgnbf(Num a,Num *c)
                    372: {
                    373:   mpfr_t r;
                    374:   BF d;
                    375:
                    376:   if ( !a )
                    377:     *c = 0;
                    378:   else if ( NID(a) <= N_A )
                    379:     (*chsgnnumt[NID(a)])(a,c);
                    380:   else {
                    381:     mpfr_init2(r,BFPREC(a));
                    382:     mpfr_neg(r,((BF)a)->body,MPFR_RNDN);
                    383:     MPFRTOBF(r,d);
                    384:     *c = (Num)d;
                    385:   }
                    386: }
                    387:
                    388: int cmpbf(Num a,Num b)
                    389: {
1.9     ! noro      390:   int ret;
        !           391:   GZ z;
        !           392:   GQ q;
        !           393:
1.7       noro      394:   if ( !a ) {
                    395:     if ( !b || (NID(b)<=N_A) )
                    396:       return (*cmpnumt[NID(b)])(a,b);
                    397:     else
                    398:       return -mpfr_sgn(((BF)a)->body);
                    399:   } else if ( !b ) {
                    400:     if ( !a || (NID(a)<=N_A) )
                    401:       return (*cmpnumt[NID(a)])(a,b);
                    402:     else
                    403:       return mpfr_sgn(((BF)a)->body);
1.9     ! noro      404:   } else if ( NID(a) == N_B ) {
        !           405:     switch ( NID(b) ) {
        !           406:     case N_Q:
        !           407:       if ( INT((Q)b) ) {
        !           408:         z = ztogz((Q)b);
        !           409:         ret = mpfr_cmp_z(((BF)a)->body,z->body);
        !           410:       } else {
        !           411:         q = qtogq((Q)b);
        !           412:         ret = mpfr_cmp_q(((BF)a)->body,q->body);
        !           413:       }
        !           414:       break;
        !           415:     case N_R:
        !           416:       /* double precision = 53 */
        !           417:       ret = mpfr_cmp_d(((BF)a)->body,((Real)b)->body);
        !           418:       break;
        !           419:     case N_B:
        !           420:       ret = mpfr_cmp(((BF)a)->body,((BF)b)->body);
        !           421:       break;
        !           422:     }
        !           423:     return ret;
        !           424:   } else { /* NID(b)==N_B */
        !           425:     switch ( NID(a) ) {
        !           426:     case N_Q:
        !           427:       if ( INT((Q)a) ) {
        !           428:         z = ztogz((Q)a);
        !           429:         ret = mpfr_cmp_z(((BF)b)->body,z->body);
        !           430:       } else {
        !           431:         q = qtogq((Q)a);
        !           432:         ret = mpfr_cmp_q(((BF)b)->body,q->body);
        !           433:       }
        !           434:       break;
        !           435:     case N_R:
        !           436:       /* double precision = 53 */
        !           437:       ret = mpfr_cmp_d(((BF)b)->body,((Real)a)->body);
        !           438:       break;
        !           439:     }
        !           440:     return -ret;
1.7       noro      441:   }
1.1       noro      442: }

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