00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ext_fmt.h"
00015 #include <float.h>
00016 #include <errno.h>
00017 #include <ctype.h>
00018
00019 static int b64_add(struct mantissa *e1, struct mantissa *e2);
00020 static b64_sft(struct mantissa *e1, int n);
00021
00022 static
00023 mul_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3)
00024 {
00025
00026
00027
00028 register int i,j;
00029 unsigned short mp[4];
00030 unsigned short mc[4];
00031 unsigned short result[8];
00032
00033 register unsigned short *pres;
00034
00035
00036 e3->sign = e1->sign ^ e2->sign;
00037
00038
00039 e3->exp = e1->exp + e2->exp + 1;
00040
00041
00042
00043
00044
00045
00046
00047 mp[0] = e1->m1 >> 16;
00048 mp[1] = (unsigned short) e1->m1;
00049 mp[2] = e1->m2 >> 16;
00050 mp[3] = (unsigned short) e1->m2;
00051 mc[0] = e2->m1 >> 16;
00052 mc[1] = (unsigned short) e2->m1;
00053 mc[2] = e2->m2 >> 16;
00054 mc[3] = (unsigned short) e2->m2;
00055 for (i = 8; i--;) {
00056 result[i] = 0;
00057 }
00058
00059
00060
00061 for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
00062 unsigned short k = 0;
00063 unsigned long mpi = mp[i];
00064 for(j=4;j--;) {
00065 unsigned long tmp = (unsigned long)pres[j] + k;
00066 if (mc[j]) tmp += mpi * mc[j];
00067 pres[j] = tmp;
00068 k = tmp >> 16;
00069 }
00070 pres[-1] = k;
00071 }
00072
00073 if (! (result[0] & 0x8000)) {
00074 e3->exp--;
00075 for (i = 0; i <= 3; i++) {
00076 result[i] <<= 1;
00077 if (result[i+1]&0x8000) result[i] |= 1;
00078 }
00079 result[4] <<= 1;
00080 }
00081
00082
00083
00084 e3->m1 = ((unsigned long)(result[0]) << 16) + result[1];
00085 e3->m2 = ((unsigned long)(result[2]) << 16) + result[3];
00086 if (result[4] & 0x8000) {
00087 if (++e3->m2 == 0) {
00088 if (++e3->m1 == 0) {
00089 e3->m1 = 0x80000000;
00090 e3->exp++;
00091 }
00092 }
00093 }
00094 }
00095
00096 static
00097 add_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3)
00098 {
00099
00100
00101
00102 struct EXTEND ce2;
00103 int diff;
00104
00105 if ((e2->m1 | e2->m2) == 0L) {
00106 *e3 = *e1;
00107 return;
00108 }
00109 if ((e1->m1 | e1->m2) == 0L) {
00110 *e3 = *e2;
00111 return;
00112 }
00113 ce2 = *e2;
00114 *e3 = *e1;
00115 e1 = &ce2;
00116
00117
00118 diff = e3->exp - e1->exp;
00119 if (diff < 0) {
00120 diff = -diff;
00121 e3->exp += diff;
00122 b64_sft(&(e3->mantissa), diff);
00123 }
00124 else if (diff > 0) {
00125 e1->exp += diff;
00126 b64_sft(&(e1->mantissa), diff);
00127 }
00128 if (e1->sign != e3->sign) {
00129
00130 if (e1->m1 > e3->m1 ||
00131 (e1->m1 == e3->m1 && e1->m2 > e3->m2)) {
00132
00133 if (e3->m2 > e1->m2) {
00134 e1->m1 -= 1;
00135 }
00136 e1->m1 -= e3->m1;
00137 e1->m2 -= e3->m2;
00138 *e3 = *e1;
00139 }
00140 else {
00141 if (e1->m2 > e3->m2)
00142 e3->m1 -= 1;
00143 e3->m1 -= e1->m1;
00144 e3->m2 -= e1->m2;
00145 }
00146 }
00147 else {
00148 if (b64_add(&e3->mantissa,&e1->mantissa)) {
00149 b64_sft(&e3->mantissa,1);
00150 e3->m1 |= 0x80000000L;
00151 e3->exp++;
00152 }
00153 }
00154 if ((e3->m2 | e3->m1) != 0L) {
00155
00156 if (e3->m1 == 0L) {
00157 e3->m1 = e3->m2; e3->m2 = 0L; e3->exp -= 32;
00158 }
00159 if (!(e3->m1 & 0x80000000)) {
00160 unsigned long l = 0x40000000;
00161 int cnt = -1;
00162
00163 while (! (l & e3->m1)) {
00164 l >>= 1; cnt--;
00165 }
00166 e3->exp += cnt;
00167 b64_sft(&(e3->mantissa), cnt);
00168 }
00169 }
00170 }
00171
00172 static int
00173 cmp_ext(struct EXTEND *e1, struct EXTEND *e2)
00174 {
00175 struct EXTEND tmp;
00176
00177 e2->sign = ! e2->sign;
00178 add_ext(e1, e2, &tmp);
00179 e2->sign = ! e2->sign;
00180 if (tmp.m1 == 0 && tmp.m2 == 0) return 0;
00181 if (tmp.sign) return -1;
00182 return 1;
00183 }
00184
00185 static
00186 b64_sft(struct mantissa *e1, int n)
00187 {
00188 if (n > 0) {
00189 if (n > 63) {
00190 e1->l_32 = 0;
00191 e1->h_32 = 0;
00192 return;
00193 }
00194 if (n >= 32) {
00195 e1->l_32 = e1->h_32;
00196 e1->h_32 = 0;
00197 n -= 32;
00198 }
00199 if (n > 0) {
00200 e1->l_32 >>= n;
00201 if (e1->h_32 != 0) {
00202 e1->l_32 |= (e1->h_32 << (32 - n));
00203 e1->h_32 >>= n;
00204 }
00205 }
00206 return;
00207 }
00208 n = -n;
00209 if (n > 0) {
00210 if (n > 63) {
00211 e1->l_32 = 0;
00212 e1->h_32 = 0;
00213 return;
00214 }
00215 if (n >= 32) {
00216 e1->h_32 = e1->l_32;
00217 e1->l_32 = 0;
00218 n -= 32;
00219 }
00220 if (n > 0) {
00221 e1->h_32 <<= n;
00222 if (e1->l_32 != 0) {
00223 e1->h_32 |= (e1->l_32 >> (32 - n));
00224 e1->l_32 <<= n;
00225 }
00226 }
00227 }
00228 }
00229
00230 static int
00231 b64_add(struct mantissa *e1, struct mantissa *e2)
00232
00233
00234
00235 {
00236 register int overflow;
00237 int carry;
00238
00239
00240 overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32);
00241 e1->h_32 += e2->h_32;
00242
00243
00244 carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32);
00245 e1->l_32 += e2->l_32;
00246 if ((carry) && (++e1->h_32 == 0))
00247 return(1);
00248 else
00249 return(overflow);
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 static struct EXTEND ten_powers[] = {
00328 { 0, 0, 0x80000000, 0 },
00329 { 0, 3, 0xA0000000, 0 },
00330 { 0, 6, 0xC8000000, 0 },
00331 { 0, 9, 0xFA000000, 0 },
00332 { 0, 13, 0x9C400000, 0 },
00333 { 0, 16, 0xC3500000, 0 },
00334 { 0, 19, 0xF4240000, 0 },
00335 { 0, 23, 0x98968000, 0 },
00336 { 0, 26, 0xBEBC2000, 0 },
00337 { 0, 29, 0xEE6B2800, 0 },
00338 { 0, 33, 0x9502F900, 0 },
00339 { 0, 36, 0xBA43B740, 0 },
00340 { 0, 39, 0xE8D4A510, 0 },
00341 { 0, 43, 0x9184E72A, 0 },
00342 { 0, 46, 0xB5E620F4, 0x80000000 },
00343 { 0, 49, 0xE35FA931, 0xA0000000 },
00344 { 0, 53, 0x8E1BC9BF, 0x04000000 },
00345 { 0, 56, 0xB1A2BC2E, 0xC5000000 },
00346 { 0, 59, 0xDE0B6B3A, 0x76400000 },
00347 { 0, 63, 0x8AC72304, 0x89E80000 },
00348 { 0, 66, 0xAD78EBC5, 0xAC620000 },
00349 { 0, 69, 0xD8D726B7, 0x177A8000 },
00350 { 0, 73, 0x87867832, 0x6EAC9000 },
00351 { 0, 76, 0xA968163F, 0x0A57B400 },
00352 { 0, 79, 0xD3C21BCE, 0xCCEDA100 },
00353 { 0, 83, 0x84595161, 0x401484A0 },
00354 { 0, 86, 0xA56FA5B9, 0x9019A5C8 },
00355 { 0, 89, 0xCECB8F27, 0xF4200F3A }
00356 };
00357 static struct EXTEND big_ten_powers[] = {
00358 { 0, 0, 0x80000000, 0 },
00359 { 0, 93, 0x813F3978, 0xF8940984 },
00360 { 0, 186, 0x82818F12, 0x81ED44A0 },
00361 { 0, 279, 0x83C7088E, 0x1AAB65DB },
00362 { 0, 372, 0x850FADC0, 0x9923329E },
00363 { 0, 465, 0x865B8692, 0x5B9BC5C2 },
00364 { 0, 558, 0x87AA9AFF, 0x79042287 },
00365 { 0, 651, 0x88FCF317, 0xF22241E2 },
00366 { 0, 744, 0x8A5296FF, 0xE33CC930 },
00367 { 0, 837, 0x8BAB8EEF, 0xB6409C1A },
00368 { 0, 930, 0x8D07E334, 0x55637EB3 },
00369 { 0, 1023, 0x8E679C2F, 0x5E44FF8F },
00370 { 0, 1116, 0x8FCAC257, 0x558EE4E6 },
00371 { 0, 1209, 0x91315E37, 0xDB165AA9 },
00372 { 0, 1302, 0x929B7871, 0xDE7F22B9 },
00373 { 0, 1395, 0x940919BB, 0xD4620B6D },
00374 { 0, 1488, 0x957A4AE1, 0xEBF7F3D4 },
00375 { 0, 1581, 0x96EF14C6, 0x454AA840 },
00376 { 0, 1674, 0x98678061, 0x27ECE4F5 },
00377 { 0, 1767, 0x99E396C1, 0x3A3ACFF2 }
00378 };
00379
00380 static struct EXTEND r_ten_powers[] = {
00381 { 0, 0, 0x80000000, 0 },
00382 { 0, -4, 0xCCCCCCCC, 0xCCCCCCCD },
00383 { 0, -7, 0xA3D70A3D, 0x70A3D70A },
00384 { 0, -10, 0x83126E97, 0x8D4FDF3B },
00385 { 0, -14, 0xD1B71758, 0xE219652C },
00386 { 0, -17, 0xA7C5AC47, 0x1B478423 },
00387 { 0, -20, 0x8637BD05, 0xAF6C69B6 },
00388 { 0, -24, 0xD6BF94D5, 0xE57A42BC },
00389 { 0, -27, 0xABCC7711, 0x8461CEFD },
00390 { 0, -30, 0x89705F41, 0x36B4A597 },
00391 { 0, -34, 0xDBE6FECE, 0xBDEDD5BF },
00392 { 0, -37, 0xAFEBFF0B, 0xCB24AAFF },
00393 { 0, -40, 0x8CBCCC09, 0x6F5088CC },
00394 { 0, -44, 0xE12E1342, 0x4BB40E13 },
00395 { 0, -47, 0xB424DC35, 0x095CD80F },
00396 { 0, -50, 0x901D7CF7, 0x3AB0ACD9 },
00397 { 0, -54, 0xE69594BE, 0xC44DE15B },
00398 { 0, -57, 0xB877AA32, 0x36A4B449 },
00399 { 0, -60, 0x9392EE8E, 0x921D5D07 },
00400 { 0, -64, 0xEC1E4A7D, 0xB69561A5 },
00401 { 0, -67, 0xBCE50864, 0x92111AEB },
00402 { 0, -70, 0x971DA050, 0x74DA7BEF },
00403 { 0, -74, 0xF1C90080, 0xBAF72CB1 },
00404 { 0, -77, 0xC16D9A00, 0x95928A27 },
00405 { 0, -80, 0x9ABE14CD, 0x44753B53 },
00406 { 0, -84, 0xF79687AE, 0xD3EEC551 },
00407 { 0, -87, 0xC6120625, 0x76589DDB },
00408 { 0, -90, 0x9E74D1B7, 0x91E07E48 }
00409 };
00410
00411 static struct EXTEND r_big_ten_powers[] = {
00412 { 0, 0, 0x80000000, 0 },
00413 { 0, -94, 0xFD87B5F2, 0x8300CA0E },
00414 { 0, -187, 0xFB158592, 0xBE068D2F },
00415 { 0, -280, 0xF8A95FCF, 0x88747D94 },
00416 { 0, -373, 0xF64335BC, 0xF065D37D },
00417 { 0, -466, 0xF3E2F893, 0xDEC3F126 },
00418 { 0, -559, 0xF18899B1, 0xBC3F8CA2 },
00419 { 0, -652, 0xEF340A98, 0x172AACE5 },
00420 { 0, -745, 0xECE53CEC, 0x4A314EBE },
00421 { 0, -838, 0xEA9C2277, 0x23EE8BCB },
00422 { 0, -931, 0xE858AD24, 0x8F5C22CA },
00423 { 0, -1024, 0xE61ACF03, 0x3D1A45DF },
00424 { 0, -1117, 0xE3E27A44, 0x4D8D98B8 },
00425 { 0, -1210, 0xE1AFA13A, 0xFBD14D6E },
00426 { 0, -1303, 0xDF82365C, 0x497B5454 },
00427 { 0, -1396, 0xDD5A2C3E, 0xAB3097CC },
00428 { 0, -1489, 0xDB377599, 0xB6074245 },
00429 { 0, -1582, 0xD91A0545, 0xCDB51186 },
00430 { 0, -1675, 0xD701CE3B, 0xD387BF48 },
00431 { 0, -1768, 0xD4EEC394, 0xD6258BF8 }
00432 };
00433
00434 #define TP (int)(sizeof(ten_powers)/sizeof(ten_powers[0]))
00435 #define BTP (int)(sizeof(big_ten_powers)/sizeof(big_ten_powers[0]))
00436 #define MAX_EXP (TP * BTP - 1)
00437
00438 static
00439 add_exponent(struct EXTEND *e, int exp)
00440 {
00441 int neg = exp < 0;
00442 int divsz, modsz;
00443 struct EXTEND x;
00444
00445 if (neg) exp = -exp;
00446 divsz = exp / TP;
00447 modsz = exp % TP;
00448 if (neg) {
00449 mul_ext(e, &r_ten_powers[modsz], &x);
00450 mul_ext(&x, &r_big_ten_powers[divsz], e);
00451 }
00452 else {
00453 mul_ext(e, &ten_powers[modsz], &x);
00454 mul_ext(&x, &big_ten_powers[divsz], e);
00455 }
00456 }
00457
00458 _str_ext_cvt(const char *s, char **ss, struct EXTEND *e)
00459 {
00460
00461 register int c;
00462 int dotseen = 0;
00463 int digitseen = 0;
00464 int exp = 0;
00465
00466 if (ss) *ss = (char *)s;
00467 while (isspace(*s)) s++;
00468
00469 e->sign = 0;
00470 e->exp = 0;
00471 e->m1 = e->m2 = 0;
00472
00473 c = *s;
00474 switch(c) {
00475 case '-':
00476 e->sign = 1;
00477 case '+':
00478 s++;
00479 }
00480 while (c = *s++, isdigit(c) || (c == '.' && ! dotseen++)) {
00481 if (c == '.') continue;
00482 digitseen = 1;
00483 if (e->m1 <= (unsigned long)(0xFFFFFFFF)/10) {
00484 struct mantissa a1;
00485
00486 a1 = e->mantissa;
00487 b64_sft(&(e->mantissa), -3);
00488 b64_sft(&a1, -1);
00489 b64_add(&(e->mantissa), &a1);
00490 a1.h_32 = 0;
00491 a1.l_32 = c - '0';
00492 b64_add(&(e->mantissa), &a1);
00493 }
00494 else exp++;
00495 if (dotseen) exp--;
00496 }
00497 if (! digitseen) return;
00498
00499 if (ss) *ss = (char *)s - 1;
00500
00501 if (c == 'E' || c == 'e') {
00502 int exp1 = 0;
00503 int sign = 1;
00504 int exp_overflow = 0;
00505
00506 switch(*s) {
00507 case '-':
00508 sign = -1;
00509 case '+':
00510 s++;
00511 }
00512 if (c = *s, isdigit(c)) {
00513 do {
00514 int tmp;
00515
00516 exp1 = 10 * exp1 + (c - '0');
00517 if ((tmp = sign * exp1 + exp) > MAX_EXP ||
00518 tmp < -MAX_EXP) {
00519 exp_overflow = 1;
00520 }
00521 } while (c = *++s, isdigit(c));
00522 if (ss) *ss = (char *)s;
00523 }
00524 exp += sign * exp1;
00525 if (exp_overflow) {
00526 exp = sign * MAX_EXP;
00527 if (e->m1 != 0 || e->m2 != 0) errno = ERANGE;
00528 }
00529 }
00530 if (e->m1 == 0 && e->m2 == 0) return;
00531 e->exp = 63;
00532 while (! (e->m1 & 0x80000000)) {
00533 b64_sft(&(e->mantissa),-1);
00534 e->exp--;
00535 }
00536 add_exponent(e, exp);
00537 }
00538
00539 #include <math.h>
00540
00541 static
00542 ten_mult(struct EXTEND *e)
00543 {
00544 struct EXTEND e1 = *e;
00545
00546 e1.exp++;
00547 e->exp += 3;
00548 add_ext(e, &e1, e);
00549 }
00550
00551 #define NDIGITS 128
00552 #define NSIGNIFICANT 19
00553
00554 char *
00555 _ext_str_cvt(struct EXTEND *e, int ndigit, int *decpt, int *sign, int ecvtflag)
00556 {
00557
00558
00559 static char buf[NDIGITS+1];
00560 struct EXTEND m;
00561 register char *p = buf;
00562 register char *pe;
00563 int findex = 0;
00564
00565 if (ndigit < 0) ndigit = 0;
00566 if (ndigit > NDIGITS) ndigit = NDIGITS;
00567 pe = &buf[ndigit];
00568 buf[0] = '\0';
00569
00570 *sign = 0;
00571 if (e->sign) {
00572 *sign = 1;
00573 e->sign = 0;
00574 }
00575
00576 *decpt = 0;
00577 if (e->m1 != 0) {
00578 register struct EXTEND *pp = &big_ten_powers[1];
00579
00580 while(cmp_ext(e,pp) >= 0) {
00581 pp++;
00582 findex = pp - big_ten_powers;
00583 if (findex >= BTP) break;
00584 }
00585 pp--;
00586 findex = pp - big_ten_powers;
00587 mul_ext(e,&r_big_ten_powers[findex],e);
00588 *decpt += findex * TP;
00589 pp = &ten_powers[1];
00590 while(pp < &ten_powers[TP] && cmp_ext(e, pp) >= 0) pp++;
00591 pp--;
00592 findex = pp - ten_powers;
00593 *decpt += findex;
00594
00595 if (cmp_ext(e, &ten_powers[0]) < 0) {
00596 pp = &r_big_ten_powers[1];
00597 while(cmp_ext(e,pp) < 0) pp++;
00598 pp--;
00599 findex = pp - r_big_ten_powers;
00600 mul_ext(e, &big_ten_powers[findex], e);
00601 *decpt -= findex * TP;
00602
00603 ten_mult(e);
00604 (*decpt)--;
00605 pp = &r_ten_powers[0];
00606 while(cmp_ext(e, pp) < 0) pp++;
00607 findex = pp - r_ten_powers;
00608 mul_ext(e, &ten_powers[findex], e);
00609 *decpt -= findex;
00610 findex = 0;
00611 }
00612 (*decpt)++;
00613 }
00614 if (! ecvtflag) {
00615
00616 pe += *decpt;
00617 if (pe > &buf[NDIGITS]) pe = &buf[NDIGITS];
00618 }
00619 m.exp = -62;
00620 m.sign = 0;
00621 m.m1 = 0xA0000000;
00622 m.m2 = 0;
00623 while (p <= pe) {
00624 struct EXTEND oneminm;
00625
00626 if (p - pe > NSIGNIFICANT) {
00627 findex = 0;
00628 e->m1 = 0;
00629 }
00630 if (findex) {
00631 struct EXTEND tc, oldtc;
00632 int count = 0;
00633
00634 oldtc.exp = 0;
00635 oldtc.sign = 0;
00636 oldtc.m1 = 0;
00637 oldtc.m2 = 0;
00638 tc = ten_powers[findex];
00639 while (cmp_ext(e, &tc) >= 0) {
00640 oldtc = tc;
00641 add_ext(&tc, &ten_powers[findex], &tc);
00642 count++;
00643 }
00644 *p++ = count + '0';
00645 oldtc.sign = 1;
00646 add_ext(e, &oldtc, e);
00647 findex--;
00648 continue;
00649 }
00650 if (e->m1) {
00651 m.sign = 1;
00652 add_ext(&ten_powers[0], &m, &oneminm);
00653 m.sign = 0;
00654 if (e->exp >= 0) {
00655 struct EXTEND x;
00656
00657 x.m2 = 0; x.exp = e->exp;
00658 x.sign = 1;
00659 x.m1 = e->m1>>(31-e->exp);
00660 *p++ = (x.m1) + '0';
00661 x.m1 = x.m1 << (31-e->exp);
00662 add_ext(e, &x, e);
00663 }
00664 else *p++ = '0';
00665
00666 if (cmp_ext(&m, e) > 0 || cmp_ext(e, &oneminm) > 0) {
00667 if (e->m1 && e->exp >= -1) *(p-1) += 1;
00668 e->m1 = 0;
00669 continue;
00670 }
00671 ten_mult(&m);
00672 ten_mult(e);
00673 }
00674 else *p++ = '0';
00675 }
00676 if (pe >= buf) {
00677 p = pe;
00678 *p += 5;
00679 while (*p > '9') {
00680 *p = '0';
00681 if (p > buf) ++*--p;
00682 else {
00683 *p = '1';
00684 ++*decpt;
00685 if (! ecvtflag) {
00686
00687
00688
00689 if (pe > buf) *pe = '0';
00690 pe++;
00691 }
00692 }
00693 }
00694 *pe = '\0';
00695 }
00696 return buf;
00697 }
00698
00699 _dbl_ext_cvt(double value, struct EXTEND *e)
00700 {
00701
00702
00703 int exponent;
00704
00705 value = frexp(value, &exponent);
00706 e->sign = value < 0.0;
00707 if (e->sign) value = -value;
00708 e->exp = exponent - 1;
00709 value *= 4294967296.0;
00710 e->m1 = value;
00711 value -= e->m1;
00712 value *= 4294967296.0;
00713 e->m2 = value;
00714 }
00715
00716 static struct EXTEND max_d;
00717
00718 double
00719 _ext_dbl_cvt(struct EXTEND *e)
00720 {
00721
00722
00723 double f;
00724 int sign = e->sign;
00725
00726 e->sign = 0;
00727 if (e->m1 == 0 && e->m2 == 0) {
00728 return 0.0;
00729 }
00730 if (max_d.exp == 0) {
00731 _dbl_ext_cvt(DBL_MAX, &max_d);
00732 }
00733 if (cmp_ext(&max_d, e) < 0) {
00734 f = HUGE_VAL;
00735 errno = ERANGE;
00736 }
00737 else f = ldexp((double)e->m1*4294967296.0 + (double)e->m2, e->exp-63);
00738 if (sign) f = -f;
00739 if (f == 0.0 && (e->m1 != 0 || e->m2 != 0)) {
00740 errno = ERANGE;
00741 }
00742 return f;
00743 }