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

1.2       noro        1: /*
1.8     ! noro        2:  * $OpenXM: OpenXM_contrib2/asir2000/engine/bf.c,v 1.7 2015/08/04 06:20:45 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);
                     88:   else {
1.8     ! noro       89:     if ( NID(a) == N_B ) {
        !            90:       switch ( NID(b) ) {
        !            91:       case N_Q:
        !            92:         mpfr_init2(r,BFPREC(a));
        !            93:         if ( INT((Q)b) ) {
        !            94:           z = ztogz((Q)b);
        !            95:           mpfr_add_z(r,((BF)a)->body,z->body,MPFR_RNDN);
        !            96:         } else {
        !            97:           q = qtogq((Q)b);
        !            98:           mpfr_add_q(r,((BF)a)->body,q->body,MPFR_RNDN);
        !            99:         }
        !           100:         break;
        !           101:       case N_R:
        !           102:         /* double precision = 53 */
        !           103:         mpfr_init2(r,MIN(BFPREC(a),53));
        !           104:         mpfr_add_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
        !           105:         break;
        !           106:       case N_B:
        !           107:         mpfr_init2(r,MIN(BFPREC(a),BFPREC(b)));
        !           108:         mpfr_add(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           109:         break;
        !           110:       }
        !           111:     } else { /* NID(b)==N_B */
        !           112:       switch ( NID(a) ) {
        !           113:       case N_Q:
        !           114:         mpfr_init2(r,BFPREC(b));
        !           115:         if ( INT((Q)a) ) {
        !           116:           z = ztogz((Q)a);
        !           117:           mpfr_add_z(r,((BF)b)->body,z->body,MPFR_RNDN);
        !           118:         } else {
        !           119:           q = qtogq((Q)a);
        !           120:           mpfr_add_q(r,((BF)b)->body,q->body,MPFR_RNDN);
        !           121:         }
        !           122:         break;
        !           123:       case N_R:
        !           124:         /* double precision = 53 */
        !           125:         mpfr_init2(r,MIN(BFPREC(b),53));
        !           126:         mpfr_add_d(r,((BF)b)->body,((Real)a)->body,MPFR_RNDN);
        !           127:         break;
        !           128:       }
        !           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);
                    148:   else {
1.8     ! noro      149:     if ( NID(a) == N_B ) {
        !           150:       switch ( NID(b) ) {
        !           151:       case N_Q:
        !           152:         mpfr_init2(r,BFPREC(a));
        !           153:         if ( INT((Q)b) ) {
        !           154:           z = ztogz((Q)b);
        !           155:           mpfr_sub_z(r,((BF)a)->body,z->body,MPFR_RNDN);
        !           156:         } else {
        !           157:           q = qtogq((Q)b);
        !           158:           mpfr_sub_q(r,((BF)a)->body,q->body,MPFR_RNDN);
        !           159:         }
        !           160:         break;
        !           161:       case N_R:
        !           162:         /* double precision = 53 */
        !           163:         mpfr_init2(r,MIN(BFPREC(a),53));
        !           164:         mpfr_sub_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
        !           165:         break;
        !           166:       case N_B:
        !           167:         mpfr_init2(r,MIN(BFPREC(a),BFPREC(b)));
        !           168:         mpfr_sub(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           169:         break;
        !           170:       }
        !           171:     } else { /* NID(b)==N_B */
        !           172:       switch ( NID(a) ) {
        !           173:       case N_Q:
        !           174:         mpfr_init2(s,BFPREC(b));
        !           175:         mpfr_init2(r,BFPREC(b));
        !           176:         if ( INT((Q)a) ) {
        !           177:           z = ztogz((Q)a);
        !           178:           mpfr_sub_z(s,((BF)b)->body,z->body,MPFR_RNDN);
        !           179:         } else {
        !           180:           q = qtogq((Q)a);
        !           181:           mpfr_sub_q(s,((BF)b)->body,q->body,MPFR_RNDN);
        !           182:         }
        !           183:         mpfr_neg(r,s,MPFR_RNDN);
        !           184:         break;
        !           185:       case N_R:
        !           186:         /* double precision = 53 */
        !           187:         mpfr_init2(r,MIN(BFPREC(b),53));
        !           188:         mpfr_d_sub(r,((Real)a)->body,((BF)b)->body,MPFR_RNDN);
        !           189:         break;
        !           190:       }
        !           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);
                    209:   else {
1.8     ! noro      210:     if ( NID(a) == N_B ) {
        !           211:       switch ( NID(b) ) {
        !           212:       case N_Q:
        !           213:         mpfr_init2(r,BFPREC(a));
        !           214:         if ( INT((Q)b) ) {
        !           215:           z = ztogz((Q)b);
        !           216:           mpfr_mul_z(r,((BF)a)->body,z->body,MPFR_RNDN);
        !           217:         } else {
        !           218:           q = qtogq((Q)b);
        !           219:           mpfr_mul_q(r,((BF)a)->body,q->body,MPFR_RNDN);
        !           220:         }
        !           221:         break;
        !           222:       case N_R:
        !           223:         /* double precision = 53 */
        !           224:         mpfr_init2(r,MIN(BFPREC(a),53));
        !           225:         mpfr_mul_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
        !           226:         break;
        !           227:       case N_B:
        !           228:         mpfr_init2(r,MIN(BFPREC(a),BFPREC(b)));
        !           229:         mpfr_mul(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           230:         break;
        !           231:       }
        !           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);
        !           242:         }
        !           243:         break;
        !           244:       case N_R:
        !           245:         /* double precision = 53 */
        !           246:         mpfr_init2(r,MIN(BFPREC(b),53));
        !           247:         mpfr_mul_d(r,((BF)b)->body,((Real)a)->body,MPFR_RNDN);
        !           248:         break;
        !           249:       }
        !           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);
                    269:   else {
1.8     ! noro      270:     if ( NID(a) == N_B ) {
        !           271:       switch ( NID(b) ) {
        !           272:       case N_Q:
        !           273:         mpfr_init2(r,BFPREC(a));
        !           274:         if ( INT((Q)b) ) {
        !           275:           z = ztogz((Q)b);
        !           276:           mpfr_div_z(r,((BF)a)->body,z->body,MPFR_RNDN);
        !           277:         } else {
        !           278:           q = qtogq((Q)b);
        !           279:           mpfr_div_q(r,((BF)a)->body,q->body,MPFR_RNDN);
        !           280:         }
        !           281:         break;
        !           282:       case N_R:
        !           283:         /* double precision = 53 */
        !           284:         mpfr_init2(r,MIN(BFPREC(a),53));
        !           285:         mpfr_div_d(r,((BF)a)->body,((Real)b)->body,MPFR_RNDN);
        !           286:         break;
        !           287:       case N_B:
        !           288:         mpfr_init2(r,MIN(BFPREC(a),BFPREC(b)));
        !           289:         mpfr_div(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           290:         break;
        !           291:       }
        !           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,MIN(BFPREC(b),53));
        !           303:         mpfr_d_div(r,((Real)a)->body,((BF)b)->body,MPFR_RNDN);
        !           304:         break;
        !           305:       }
        !           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);
                    325:   else {
1.8     ! noro      326:     if ( NID(a) == N_B ) {
        !           327:       switch ( NID(b) ) {
        !           328:       case N_Q:
        !           329:         mpfr_init2(r,BFPREC(a));
        !           330:         if ( INT((Q)b) ) {
        !           331:           z = ztogz((Q)b);
        !           332:           mpfr_pow_z(r,((BF)a)->body,z->body,MPFR_RNDN);
        !           333:         } else {
        !           334:           b = tobf(b,BFPREC(a));
        !           335:           mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           336:         }
        !           337:         break;
        !           338:       case N_R:
        !           339:         /* double precision = 53 */
        !           340:         prec = MIN(BFPREC(a),53);
        !           341:         mpfr_init2(r,prec);
        !           342:         b = tobf(b,prec);
        !           343:         mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           344:         break;
        !           345:       case N_B:
        !           346:         mpfr_init2(r,MIN(BFPREC(a),BFPREC(b)));
        !           347:         mpfr_pow(r,((BF)a)->body,((BF)b)->body,MPFR_RNDN);
        !           348:         break;
        !           349:       }
        !           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 = MIN(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;
        !           364:       }
        !           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: {
                    390:   if ( !a ) {
                    391:     if ( !b || (NID(b)<=N_A) )
                    392:       return (*cmpnumt[NID(b)])(a,b);
                    393:     else
                    394:       return -mpfr_sgn(((BF)a)->body);
                    395:   } else if ( !b ) {
                    396:     if ( !a || (NID(a)<=N_A) )
                    397:       return (*cmpnumt[NID(a)])(a,b);
                    398:     else
                    399:       return mpfr_sgn(((BF)a)->body);
                    400:   } else {
                    401:     if ( NID(a) != N_B ) a = tobf(a,0);
                    402:     if ( NID(b) != N_B ) b = tobf(b,0);
                    403:     return mpfr_cmp(((BF)a)->body,((BF)b)->body);
                    404:   }
1.1       noro      405: }

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