Annotation of previous_trunk/src/softfloat/fsincos.c, revision 1.1

1.1     ! root        1: /*============================================================================
        !             2: This source file is an extension to the SoftFloat IEC/IEEE Floating-point
        !             3: Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
        !             4: floating point emulation.
        !             5: 
        !             6: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
        !             7: been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
        !             8: RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
        !             9: AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
        !            10: COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
        !            11: EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
        !            12: INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
        !            13: OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
        !            14: 
        !            15: Derivative works are acceptable, even for commercial purposes, so long as
        !            16: (1) the source code for the derivative work includes prominent notice that
        !            17: the work is derivative, and (2) the source code includes prominent notice with
        !            18: these four paragraphs for those parts of this code that are retained.
        !            19: =============================================================================*/
        !            20: 
        !            21: /*============================================================================
        !            22:  * Written for Bochs (x86 achitecture simulator) by
        !            23:  *            Stanislav Shwartsman [sshwarts at sourceforge net]
        !            24:  * ==========================================================================*/
        !            25: 
        !            26: #define FLOAT128
        !            27: 
        !            28: #define USE_estimateDiv128To64
        !            29: #include "mamesf.h"
        !            30: #include "softfloat.h"
        !            31: #include "fpu_constant.h"
        !            32: 
        !            33: static const floatx80 floatx80_one = { 0x3fff, 0x8000000000000000U };
        !            34: static const floatx80 floatx80_default_nan = { floatx80_default_nan_high, floatx80_default_nan_low };
        !            35: 
        !            36: #define packFloat2x128m(zHi, zLo) {(zHi), (zLo)}
        !            37: #define PACK_FLOAT_128(hi,lo) packFloat2x128m(LIT64(hi),LIT64(lo))
        !            38: 
        !            39: #define EXP_BIAS 0x3FFF
        !            40: 
        !            41: 
        !            42: /* reduce trigonometric function argument using 128-bit precision
        !            43:    M_PI approximation */
        !            44: static uint64_t argument_reduction_kernel(uint64_t aSig0, int Exp, uint64_t *zSig0, uint64_t *zSig1)
        !            45: {
        !            46:        uint64_t term0, term1, term2;
        !            47:        uint64_t aSig1 = 0;
        !            48: 
        !            49:        shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0);
        !            50:        uint64_t q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI);
        !            51:        mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2);
        !            52:        sub128(aSig1, aSig0, term0, term1, zSig1, zSig0);
        !            53:        while ((int64_t)(*zSig1) < 0) {
        !            54:                --q;
        !            55:                add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2);
        !            56:        }
        !            57:        *zSig1 = term2;
        !            58:        return q;
        !            59: }
        !            60: 
        !            61: static int reduce_trig_arg(int expDiff, int *zSign, uint64_t *aSig0, uint64_t *aSig1)
        !            62: {
        !            63:        uint64_t term0, term1, q = 0;
        !            64: 
        !            65:        if (expDiff < 0) {
        !            66:                shift128Right(*aSig0, 0, 1, aSig0, aSig1);
        !            67:                expDiff = 0;
        !            68:        }
        !            69:        if (expDiff > 0) {
        !            70:                q = argument_reduction_kernel(*aSig0, expDiff, aSig0, aSig1);
        !            71:        }
        !            72:        else {
        !            73:                if (FLOAT_PI_HI <= *aSig0) {
        !            74:                        *aSig0 -= FLOAT_PI_HI;
        !            75:                        q = 1;
        !            76:                }
        !            77:        }
        !            78: 
        !            79:        shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1);
        !            80:        if (! lt128(*aSig0, *aSig1, term0, term1))
        !            81:        {
        !            82:                int lt = lt128(term0, term1, *aSig0, *aSig1);
        !            83:                int eq = eq128(*aSig0, *aSig1, term0, term1);
        !            84: 
        !            85:                if ((eq && (q & 1)) || lt) {
        !            86:                        *zSign = !(*zSign);
        !            87:                        ++q;
        !            88:                }
        !            89:                if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, *aSig0, *aSig1, aSig0, aSig1);
        !            90:        }
        !            91: 
        !            92:        return (int)(q & 3);
        !            93: }
        !            94: 
        !            95: #define SIN_ARR_SIZE 11
        !            96: #define COS_ARR_SIZE 11
        !            97: 
        !            98: static float128 sin_arr[SIN_ARR_SIZE] =
        !            99: {
        !           100:        PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /*  1 */
        !           101:        PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /*  3 */
        !           102:        PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /*  5 */
        !           103:        PACK_FLOAT_128(0xbff2a01a01a01a01, 0xa01a01a01a01a01a), /*  7 */
        !           104:        PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /*  9 */
        !           105:        PACK_FLOAT_128(0xbfe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */
        !           106:        PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */
        !           107:        PACK_FLOAT_128(0xbfd6ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 15 */
        !           108:        PACK_FLOAT_128(0x3fce952c77030ad4, 0xa6b2605197771b00), /* 17 */
        !           109:        PACK_FLOAT_128(0xbfc62f49b4681415, 0x724ca1ec3b7b9675), /* 19 */
        !           110:        PACK_FLOAT_128(0x3fbd71b8ef6dcf57, 0x18bef146fcee6e45)  /* 21 */
        !           111: };
        !           112: 
        !           113: static float128 cos_arr[COS_ARR_SIZE] =
        !           114: {
        !           115:        PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /*  0 */
        !           116:        PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /*  2 */
        !           117:        PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /*  4 */
        !           118:        PACK_FLOAT_128(0xbff56c16c16c16c1, 0x6c16c16c16c16c17), /*  6 */
        !           119:        PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /*  8 */
        !           120:        PACK_FLOAT_128(0xbfe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */
        !           121:        PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */
        !           122:        PACK_FLOAT_128(0xbfda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */
        !           123:        PACK_FLOAT_128(0x3fd2ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 16 */
        !           124:        PACK_FLOAT_128(0xbfca6827863b97d9, 0x77bb004886a2c2ab), /* 18 */
        !           125:        PACK_FLOAT_128(0x3fc1e542ba402022, 0x507a9cad2bf8f0bb)  /* 20 */
        !           126: };
        !           127: 
        !           128: extern float128 OddPoly (float128 x, float128 *arr, unsigned n);
        !           129: 
        !           130: /* 0 <= x <= pi/4 */
        !           131: INLINE float128 poly_sin(float128 x)
        !           132: {
        !           133:        //                 3     5     7     9     11     13     15
        !           134:        //                x     x     x     x     x      x      x
        !           135:        // sin (x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- =
        !           136:        //                3!    5!    7!    9!    11!    13!    15!
        !           137:        //
        !           138:        //                 2     4     6     8     10     12     14
        !           139:        //                x     x     x     x     x      x      x
        !           140:        //   = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- ] =
        !           141:        //                3!    5!    7!    9!    11!    13!    15!
        !           142:        //
        !           143:        //           3                          3
        !           144:        //          --       4k                --        4k+2
        !           145:        //   p(x) = >  C  * x   > 0     q(x) = >  C   * x     < 0
        !           146:        //          --  2k                     --  2k+1
        !           147:        //          k=0                        k=0
        !           148:        //
        !           149:        //                          2
        !           150:        //   sin(x) ~ x * [ p(x) + x * q(x) ]
        !           151:        //
        !           152: 
        !           153:        return OddPoly(x, sin_arr, SIN_ARR_SIZE);
        !           154: }
        !           155: 
        !           156: extern float128 EvenPoly(float128 x, float128 *arr, unsigned n);
        !           157: 
        !           158: /* 0 <= x <= pi/4 */
        !           159: INLINE float128 poly_cos(float128 x)
        !           160: {
        !           161:        //                 2     4     6     8     10     12     14
        !           162:        //                x     x     x     x     x      x      x
        !           163:        // cos (x) ~ 1 - --- + --- - --- + --- - ---- + ---- - ----
        !           164:        //                2!    4!    6!    8!    10!    12!    14!
        !           165:        //
        !           166:        //           3                          3
        !           167:        //          --       4k                --        4k+2
        !           168:        //   p(x) = >  C  * x   > 0     q(x) = >  C   * x     < 0
        !           169:        //          --  2k                     --  2k+1
        !           170:        //          k=0                        k=0
        !           171:        //
        !           172:        //                      2
        !           173:        //   cos(x) ~ [ p(x) + x * q(x) ]
        !           174:        //
        !           175: 
        !           176:        return EvenPoly(x, cos_arr, COS_ARR_SIZE);
        !           177: }
        !           178: 
        !           179: INLINE void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
        !           180: {
        !           181:        if (sin_a) *sin_a = a;
        !           182:        if (cos_a) *cos_a = a;
        !           183: }
        !           184: 
        !           185: INLINE void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
        !           186: {
        !           187:        if (sin_a) *sin_a = a;
        !           188:        if (cos_a) *cos_a = floatx80_one;
        !           189: }
        !           190: 
        !           191: static floatx80 sincos_approximation(int neg, float128 r, uint64_t quotient)
        !           192: {
        !           193:        if (quotient & 0x1) {
        !           194:                r = poly_cos(r);
        !           195:                neg = 0;
        !           196:        } else  {
        !           197:                r = poly_sin(r);
        !           198:        }
        !           199: 
        !           200:        floatx80 result = float128_to_floatx80(r);
        !           201:        if (quotient & 0x2)
        !           202:                neg = ! neg;
        !           203: 
        !           204:        if (neg)
        !           205:                result = floatx80_chs(result);
        !           206: 
        !           207:        return result;
        !           208: }
        !           209: 
        !           210: // =================================================
        !           211: // SFFSINCOS               Compute sin(x) and cos(x)
        !           212: // =================================================
        !           213: 
        !           214: //
        !           215: // Uses the following identities:
        !           216: // ----------------------------------------------------------
        !           217: //
        !           218: //  sin(-x) = -sin(x)
        !           219: //  cos(-x) =  cos(x)
        !           220: //
        !           221: //  sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y)
        !           222: //  cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y)
        !           223: //
        !           224: //  sin(x+ pi/2)  =  cos(x)
        !           225: //  sin(x+ pi)    = -sin(x)
        !           226: //  sin(x+3pi/2)  = -cos(x)
        !           227: //  sin(x+2pi)    =  sin(x)
        !           228: //
        !           229: 
        !           230: int sf_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a)
        !           231: {
        !           232:        uint64_t aSig0, aSig1 = 0;
        !           233:        int32_t aExp, zExp, expDiff;
        !           234:        int aSign, zSign;
        !           235:        int q = 0;
        !           236: 
        !           237:        aSig0 = extractFloatx80Frac(a);
        !           238:        aExp = extractFloatx80Exp(a);
        !           239:        aSign = extractFloatx80Sign(a);
        !           240: 
        !           241:        /* invalid argument */
        !           242:        if (aExp == 0x7FFF) {
        !           243:                if ((uint64_t) (aSig0<<1)) {
        !           244:                        sincos_invalid(sin_a, cos_a, propagateFloatx80NaNOneArg(a));
        !           245:                        return 0;
        !           246:                }
        !           247: 
        !           248:                float_raise(float_flag_invalid);
        !           249:                sincos_invalid(sin_a, cos_a, floatx80_default_nan);
        !           250:                return 0;
        !           251:        }
        !           252: 
        !           253:        if (aExp == 0) {
        !           254:                if (aSig0 == 0) {
        !           255:                        sincos_tiny_argument(sin_a, cos_a, a);
        !           256:                        return 0;
        !           257:                }
        !           258: 
        !           259: //        float_raise(float_flag_denormal);
        !           260: 
        !           261:                /* handle pseudo denormals */
        !           262:                if (! (aSig0 & 0x8000000000000000U))
        !           263:                {
        !           264:                        float_raise(float_flag_inexact);
        !           265:                        if (sin_a)
        !           266:                                float_raise(float_flag_underflow);
        !           267:                        sincos_tiny_argument(sin_a, cos_a, a);
        !           268:                        return 0;
        !           269:                }
        !           270: 
        !           271:                normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
        !           272:        }
        !           273: 
        !           274:        zSign = aSign;
        !           275:        zExp = EXP_BIAS;
        !           276:        expDiff = aExp - zExp;
        !           277: 
        !           278:        /* argument is out-of-range */
        !           279:        if (expDiff >= 63)
        !           280:                return -1;
        !           281: 
        !           282:        float_raise(float_flag_inexact);
        !           283: 
        !           284:        if (expDiff < -1) {    // doesn't require reduction
        !           285:                if (expDiff <= -68) {
        !           286:                        a = packFloatx80(aSign, aExp, aSig0);
        !           287:                        sincos_tiny_argument(sin_a, cos_a, a);
        !           288:                        return 0;
        !           289:                }
        !           290:                zExp = aExp;
        !           291:        }
        !           292:        else {
        !           293:                q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1);
        !           294:        }
        !           295: 
        !           296:        /* **************************** */
        !           297:        /* argument reduction completed */
        !           298:        /* **************************** */
        !           299: 
        !           300:        /* using float128 for approximation */
        !           301:        float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1);
        !           302: 
        !           303:        if (aSign) q = -q;
        !           304:        if (cos_a) *cos_a = sincos_approximation(zSign, r, q+1);
        !           305:        if (sin_a) *sin_a = sincos_approximation(zSign, r,   q);
        !           306: 
        !           307:        return 0;
        !           308: }
        !           309: 
        !           310: int floatx80_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a)
        !           311: {
        !           312:     return sf_fsincos(a, sin_a, cos_a);
        !           313: }
        !           314: 
        !           315: int floatx80_fsin(floatx80 *a)
        !           316: {
        !           317:        return sf_fsincos(*a, a, 0);
        !           318: }
        !           319: 
        !           320: int floatx80_fcos(floatx80 *a)
        !           321: {
        !           322:        return sf_fsincos(*a, 0, a);
        !           323: }
        !           324: 
        !           325: // =================================================
        !           326: // FPTAN                 Compute tan(x)
        !           327: // =================================================
        !           328: 
        !           329: //
        !           330: // Uses the following identities:
        !           331: //
        !           332: // 1. ----------------------------------------------------------
        !           333: //
        !           334: //  sin(-x) = -sin(x)
        !           335: //  cos(-x) =  cos(x)
        !           336: //
        !           337: //  sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y)
        !           338: //  cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y)
        !           339: //
        !           340: //  sin(x+ pi/2)  =  cos(x)
        !           341: //  sin(x+ pi)    = -sin(x)
        !           342: //  sin(x+3pi/2)  = -cos(x)
        !           343: //  sin(x+2pi)    =  sin(x)
        !           344: //
        !           345: // 2. ----------------------------------------------------------
        !           346: //
        !           347: //           sin(x)
        !           348: //  tan(x) = ------
        !           349: //           cos(x)
        !           350: //
        !           351: 
        !           352: int floatx80_ftan(floatx80 *a)
        !           353: {
        !           354:        uint64_t aSig0, aSig1 = 0;
        !           355:        int32_t aExp, zExp, expDiff;
        !           356:        int aSign, zSign;
        !           357:        int q = 0;
        !           358: 
        !           359:        aSig0 = extractFloatx80Frac(*a);
        !           360:        aExp = extractFloatx80Exp(*a);
        !           361:        aSign = extractFloatx80Sign(*a);
        !           362: 
        !           363:        /* invalid argument */
        !           364:        if (aExp == 0x7FFF) {
        !           365:                if ((uint64_t) (aSig0<<1))
        !           366:                {
        !           367:                        *a = propagateFloatx80NaNOneArg(*a);
        !           368:                        return 0;
        !           369:                }
        !           370: 
        !           371:                float_raise(float_flag_invalid);
        !           372:                *a = floatx80_default_nan;
        !           373:                return 0;
        !           374:        }
        !           375: 
        !           376:        if (aExp == 0) {
        !           377:                if (aSig0 == 0) return 0;
        !           378: //        float_raise(float_flag_denormal);
        !           379:                /* handle pseudo denormals */
        !           380:                if (! (aSig0 & 0x8000000000000000U))
        !           381:                {
        !           382:                        float_raise(float_flag_inexact | float_flag_underflow);
        !           383:                        return 0;
        !           384:                }
        !           385:                normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
        !           386:        }
        !           387: 
        !           388:        zSign = aSign;
        !           389:        zExp = EXP_BIAS;
        !           390:        expDiff = aExp - zExp;
        !           391: 
        !           392:        /* argument is out-of-range */
        !           393:        if (expDiff >= 63)
        !           394:                return -1;
        !           395: 
        !           396:        float_raise(float_flag_inexact);
        !           397: 
        !           398:        if (expDiff < -1) {    // doesn't require reduction
        !           399:                if (expDiff <= -68) {
        !           400:                        *a = packFloatx80(aSign, aExp, aSig0);
        !           401:                        return 0;
        !           402:                }
        !           403:                zExp = aExp;
        !           404:        }
        !           405:        else {
        !           406:                q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1);
        !           407:        }
        !           408: 
        !           409:        /* **************************** */
        !           410:        /* argument reduction completed */
        !           411:        /* **************************** */
        !           412: 
        !           413:        /* using float128 for approximation */
        !           414:        float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1);
        !           415: 
        !           416:        float128 sin_r = poly_sin(r);
        !           417:        float128 cos_r = poly_cos(r);
        !           418: 
        !           419:        if (q & 0x1) {
        !           420:                r = float128_div(cos_r, sin_r);
        !           421:                zSign = ! zSign;
        !           422:        } else {
        !           423:                r = float128_div(sin_r, cos_r);
        !           424:        }
        !           425: 
        !           426:        *a = float128_to_floatx80(r);
        !           427:        if (zSign)
        !           428:                *a = floatx80_chs(*a);
        !           429: 
        !           430:        return 0;
        !           431: }
        !           432: 
        !           433: //                            2         3         4               n
        !           434: // f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
        !           435: //         0    1         2         3         4               n
        !           436: //
        !           437: //          --       2k                --        2k+1
        !           438: //   p(x) = >  C  * x           q(x) = >  C   * x
        !           439: //          --  2k                     --  2k+1
        !           440: //
        !           441: //   f(x) ~ [ p(x) + x * q(x) ]
        !           442: //
        !           443: 
        !           444: float128 EvalPoly(float128 x, float128 *arr, unsigned n)
        !           445: {
        !           446:        float128 x2 = float128_mul(x, x);
        !           447:        unsigned i;
        !           448: 
        !           449:        assert(n > 1);
        !           450: 
        !           451:        float128 r1 = arr[--n];
        !           452:        i = n;
        !           453:        while(i >= 2) {
        !           454:                r1 = float128_mul(r1, x2);
        !           455:                i -= 2;
        !           456:                r1 = float128_add(r1, arr[i]);
        !           457:        }
        !           458:        if (i) r1 = float128_mul(r1, x);
        !           459: 
        !           460:        float128 r2 = arr[--n];
        !           461:        i = n;
        !           462:        while(i >= 2) {
        !           463:                r2 = float128_mul(r2, x2);
        !           464:                i -= 2;
        !           465:                r2 = float128_add(r2, arr[i]);
        !           466:        }
        !           467:        if (i) r2 = float128_mul(r2, x);
        !           468: 
        !           469:        return float128_add(r1, r2);
        !           470: }
        !           471: 
        !           472: //                  2         4         6         8               2n
        !           473: // f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
        !           474: //         0    1         2         3         4               n
        !           475: //
        !           476: //          --       4k                --        4k+2
        !           477: //   p(x) = >  C  * x           q(x) = >  C   * x
        !           478: //          --  2k                     --  2k+1
        !           479: //
        !           480: //                    2
        !           481: //   f(x) ~ [ p(x) + x * q(x) ]
        !           482: //
        !           483: 
        !           484: float128 EvenPoly(float128 x, float128 *arr, unsigned n)
        !           485: {
        !           486:                return EvalPoly(float128_mul(x, x), arr, n);
        !           487: }
        !           488: 
        !           489: //                        3         5         7         9               2n+1
        !           490: // f(x) ~ (C * x) + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
        !           491: //          0         1         2         3         4               n
        !           492: //                        2         4         6         8               2n
        !           493: //      = x * [ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
        !           494: //               0    1         2         3         4               n
        !           495: //
        !           496: //          --       4k                --        4k+2
        !           497: //   p(x) = >  C  * x           q(x) = >  C   * x
        !           498: //          --  2k                     --  2k+1
        !           499: //
        !           500: //                        2
        !           501: //   f(x) ~ x * [ p(x) + x * q(x) ]
        !           502: //
        !           503: 
        !           504: float128 OddPoly(float128 x, float128 *arr, unsigned n)
        !           505: {
        !           506:                return float128_mul(x, EvenPoly(x, arr, n));
        !           507: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.