Annotation of quakeworld/client/mathlib.c, revision 1.1

1.1     ! root        1: /*
        !             2: Copyright (C) 1996-1997 Id Software, Inc.
        !             3: 
        !             4: This program is free software; you can redistribute it and/or
        !             5: modify it under the terms of the GNU General Public License
        !             6: as published by the Free Software Foundation; either version 2
        !             7: of the License, or (at your option) any later version.
        !             8: 
        !             9: This program is distributed in the hope that it will be useful,
        !            10: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
        !            12: 
        !            13: See the GNU General Public License for more details.
        !            14: 
        !            15: You should have received a copy of the GNU General Public License
        !            16: along with this program; if not, write to the Free Software
        !            17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        !            18: 
        !            19: */
        !            20: // mathlib.c -- math primitives
        !            21: 
        !            22: #include <math.h>
        !            23: #include "quakedef.h"
        !            24: 
        !            25: void Sys_Error (char *error, ...);
        !            26: 
        !            27: vec3_t vec3_origin = {0,0,0};
        !            28: int nanmask = 255<<23;
        !            29: 
        !            30: /*-----------------------------------------------------------------*/
        !            31: 
        !            32: #define DEG2RAD( a ) ( a * M_PI ) / 180.0F
        !            33: 
        !            34: void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
        !            35: {
        !            36:        float d;
        !            37:        vec3_t n;
        !            38:        float inv_denom;
        !            39: 
        !            40:        inv_denom = 1.0F / DotProduct( normal, normal );
        !            41: 
        !            42:        d = DotProduct( normal, p ) * inv_denom;
        !            43: 
        !            44:        n[0] = normal[0] * inv_denom;
        !            45:        n[1] = normal[1] * inv_denom;
        !            46:        n[2] = normal[2] * inv_denom;
        !            47: 
        !            48:        dst[0] = p[0] - d * n[0];
        !            49:        dst[1] = p[1] - d * n[1];
        !            50:        dst[2] = p[2] - d * n[2];
        !            51: }
        !            52: 
        !            53: /*
        !            54: ** assumes "src" is normalized
        !            55: */
        !            56: void PerpendicularVector( vec3_t dst, const vec3_t src )
        !            57: {
        !            58:        int     pos;
        !            59:        int i;
        !            60:        float minelem = 1.0F;
        !            61:        vec3_t tempvec;
        !            62: 
        !            63:        /*
        !            64:        ** find the smallest magnitude axially aligned vector
        !            65:        */
        !            66:        for ( pos = 0, i = 0; i < 3; i++ )
        !            67:        {
        !            68:                if ( fabs( src[i] ) < minelem )
        !            69:                {
        !            70:                        pos = i;
        !            71:                        minelem = fabs( src[i] );
        !            72:                }
        !            73:        }
        !            74:        tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
        !            75:        tempvec[pos] = 1.0F;
        !            76: 
        !            77:        /*
        !            78:        ** project the point onto the plane defined by src
        !            79:        */
        !            80:        ProjectPointOnPlane( dst, tempvec, src );
        !            81: 
        !            82:        /*
        !            83:        ** normalize the result
        !            84:        */
        !            85:        VectorNormalize( dst );
        !            86: }
        !            87: 
        !            88: #ifdef _WIN32
        !            89: #pragma optimize( "", off )
        !            90: #endif
        !            91: 
        !            92: 
        !            93: void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
        !            94: {
        !            95:        float   m[3][3];
        !            96:        float   im[3][3];
        !            97:        float   zrot[3][3];
        !            98:        float   tmpmat[3][3];
        !            99:        float   rot[3][3];
        !           100:        int     i;
        !           101:        vec3_t vr, vup, vf;
        !           102: 
        !           103:        vf[0] = dir[0];
        !           104:        vf[1] = dir[1];
        !           105:        vf[2] = dir[2];
        !           106: 
        !           107:        PerpendicularVector( vr, dir );
        !           108:        CrossProduct( vr, vf, vup );
        !           109: 
        !           110:        m[0][0] = vr[0];
        !           111:        m[1][0] = vr[1];
        !           112:        m[2][0] = vr[2];
        !           113: 
        !           114:        m[0][1] = vup[0];
        !           115:        m[1][1] = vup[1];
        !           116:        m[2][1] = vup[2];
        !           117: 
        !           118:        m[0][2] = vf[0];
        !           119:        m[1][2] = vf[1];
        !           120:        m[2][2] = vf[2];
        !           121: 
        !           122:        memcpy( im, m, sizeof( im ) );
        !           123: 
        !           124:        im[0][1] = m[1][0];
        !           125:        im[0][2] = m[2][0];
        !           126:        im[1][0] = m[0][1];
        !           127:        im[1][2] = m[2][1];
        !           128:        im[2][0] = m[0][2];
        !           129:        im[2][1] = m[1][2];
        !           130: 
        !           131:        memset( zrot, 0, sizeof( zrot ) );
        !           132:        zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
        !           133: 
        !           134:        zrot[0][0] = cos( DEG2RAD( degrees ) );
        !           135:        zrot[0][1] = sin( DEG2RAD( degrees ) );
        !           136:        zrot[1][0] = -sin( DEG2RAD( degrees ) );
        !           137:        zrot[1][1] = cos( DEG2RAD( degrees ) );
        !           138: 
        !           139:        R_ConcatRotations( m, zrot, tmpmat );
        !           140:        R_ConcatRotations( tmpmat, im, rot );
        !           141: 
        !           142:        for ( i = 0; i < 3; i++ )
        !           143:        {
        !           144:                dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
        !           145:        }
        !           146: }
        !           147: 
        !           148: #ifdef _WIN32
        !           149: #pragma optimize( "", on )
        !           150: #endif
        !           151: 
        !           152: /*-----------------------------------------------------------------*/
        !           153: 
        !           154: float  anglemod(float a)
        !           155: {
        !           156: #if 0
        !           157:        if (a >= 0)
        !           158:                a -= 360*(int)(a/360);
        !           159:        else
        !           160:                a += 360*( 1 + (int)(-a/360) );
        !           161: #endif
        !           162:        a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
        !           163:        return a;
        !           164: }
        !           165: 
        !           166: /*
        !           167: ==================
        !           168: BOPS_Error
        !           169: 
        !           170: Split out like this for ASM to call.
        !           171: ==================
        !           172: */
        !           173: void BOPS_Error (void)
        !           174: {
        !           175:        Sys_Error ("BoxOnPlaneSide:  Bad signbits");
        !           176: }
        !           177: 
        !           178: #if !id386
        !           179: 
        !           180: /*
        !           181: ==================
        !           182: BoxOnPlaneSide
        !           183: 
        !           184: Returns 1, 2, or 1 + 2
        !           185: ==================
        !           186: */
        !           187: int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p)
        !           188: {
        !           189:        float   dist1, dist2;
        !           190:        int             sides;
        !           191: 
        !           192: #if 0  // this is done by the BOX_ON_PLANE_SIDE macro before calling this
        !           193:                // function
        !           194: // fast axial cases
        !           195:        if (p->type < 3)
        !           196:        {
        !           197:                if (p->dist <= emins[p->type])
        !           198:                        return 1;
        !           199:                if (p->dist >= emaxs[p->type])
        !           200:                        return 2;
        !           201:                return 3;
        !           202:        }
        !           203: #endif
        !           204:        
        !           205: // general case
        !           206:        switch (p->signbits)
        !           207:        {
        !           208:        case 0:
        !           209: dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
        !           210: dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
        !           211:                break;
        !           212:        case 1:
        !           213: dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
        !           214: dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
        !           215:                break;
        !           216:        case 2:
        !           217: dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
        !           218: dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
        !           219:                break;
        !           220:        case 3:
        !           221: dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
        !           222: dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
        !           223:                break;
        !           224:        case 4:
        !           225: dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
        !           226: dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
        !           227:                break;
        !           228:        case 5:
        !           229: dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
        !           230: dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
        !           231:                break;
        !           232:        case 6:
        !           233: dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
        !           234: dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
        !           235:                break;
        !           236:        case 7:
        !           237: dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
        !           238: dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
        !           239:                break;
        !           240:        default:
        !           241:                dist1 = dist2 = 0;              // shut up compiler
        !           242:                BOPS_Error ();
        !           243:                break;
        !           244:        }
        !           245: 
        !           246: #if 0
        !           247:        int             i;
        !           248:        vec3_t  corners[2];
        !           249: 
        !           250:        for (i=0 ; i<3 ; i++)
        !           251:        {
        !           252:                if (plane->normal[i] < 0)
        !           253:                {
        !           254:                        corners[0][i] = emins[i];
        !           255:                        corners[1][i] = emaxs[i];
        !           256:                }
        !           257:                else
        !           258:                {
        !           259:                        corners[1][i] = emins[i];
        !           260:                        corners[0][i] = emaxs[i];
        !           261:                }
        !           262:        }
        !           263:        dist = DotProduct (plane->normal, corners[0]) - plane->dist;
        !           264:        dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
        !           265:        sides = 0;
        !           266:        if (dist1 >= 0)
        !           267:                sides = 1;
        !           268:        if (dist2 < 0)
        !           269:                sides |= 2;
        !           270: 
        !           271: #endif
        !           272: 
        !           273:        sides = 0;
        !           274:        if (dist1 >= p->dist)
        !           275:                sides = 1;
        !           276:        if (dist2 < p->dist)
        !           277:                sides |= 2;
        !           278: 
        !           279: #ifdef PARANOID
        !           280: if (sides == 0)
        !           281:        Sys_Error ("BoxOnPlaneSide: sides==0");
        !           282: #endif
        !           283: 
        !           284:        return sides;
        !           285: }
        !           286: 
        !           287: #endif
        !           288: 
        !           289: 
        !           290: void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
        !           291: {
        !           292:        float           angle;
        !           293:        float           sr, sp, sy, cr, cp, cy;
        !           294:        
        !           295:        angle = angles[YAW] * (M_PI*2 / 360);
        !           296:        sy = sin(angle);
        !           297:        cy = cos(angle);
        !           298:        angle = angles[PITCH] * (M_PI*2 / 360);
        !           299:        sp = sin(angle);
        !           300:        cp = cos(angle);
        !           301:        angle = angles[ROLL] * (M_PI*2 / 360);
        !           302:        sr = sin(angle);
        !           303:        cr = cos(angle);
        !           304: 
        !           305:        forward[0] = cp*cy;
        !           306:        forward[1] = cp*sy;
        !           307:        forward[2] = -sp;
        !           308:        right[0] = (-1*sr*sp*cy+-1*cr*-sy);
        !           309:        right[1] = (-1*sr*sp*sy+-1*cr*cy);
        !           310:        right[2] = -1*sr*cp;
        !           311:        up[0] = (cr*sp*cy+-sr*-sy);
        !           312:        up[1] = (cr*sp*sy+-sr*cy);
        !           313:        up[2] = cr*cp;
        !           314: }
        !           315: 
        !           316: int VectorCompare (vec3_t v1, vec3_t v2)
        !           317: {
        !           318:        int             i;
        !           319:        
        !           320:        for (i=0 ; i<3 ; i++)
        !           321:                if (v1[i] != v2[i])
        !           322:                        return 0;
        !           323:                        
        !           324:        return 1;
        !           325: }
        !           326: 
        !           327: void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
        !           328: {
        !           329:        vecc[0] = veca[0] + scale*vecb[0];
        !           330:        vecc[1] = veca[1] + scale*vecb[1];
        !           331:        vecc[2] = veca[2] + scale*vecb[2];
        !           332: }
        !           333: 
        !           334: 
        !           335: vec_t _DotProduct (vec3_t v1, vec3_t v2)
        !           336: {
        !           337:        return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
        !           338: }
        !           339: 
        !           340: void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
        !           341: {
        !           342:        out[0] = veca[0]-vecb[0];
        !           343:        out[1] = veca[1]-vecb[1];
        !           344:        out[2] = veca[2]-vecb[2];
        !           345: }
        !           346: 
        !           347: void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
        !           348: {
        !           349:        out[0] = veca[0]+vecb[0];
        !           350:        out[1] = veca[1]+vecb[1];
        !           351:        out[2] = veca[2]+vecb[2];
        !           352: }
        !           353: 
        !           354: void _VectorCopy (vec3_t in, vec3_t out)
        !           355: {
        !           356:        out[0] = in[0];
        !           357:        out[1] = in[1];
        !           358:        out[2] = in[2];
        !           359: }
        !           360: 
        !           361: void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
        !           362: {
        !           363:        cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
        !           364:        cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
        !           365:        cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
        !           366: }
        !           367: 
        !           368: double sqrt(double x);
        !           369: 
        !           370: vec_t Length(vec3_t v)
        !           371: {
        !           372:        int             i;
        !           373:        float   length;
        !           374:        
        !           375:        length = 0;
        !           376:        for (i=0 ; i< 3 ; i++)
        !           377:                length += v[i]*v[i];
        !           378:        length = sqrt (length);         // FIXME
        !           379: 
        !           380:        return length;
        !           381: }
        !           382: 
        !           383: float VectorNormalize (vec3_t v)
        !           384: {
        !           385:        float   length, ilength;
        !           386: 
        !           387:        length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
        !           388:        length = sqrt (length);         // FIXME
        !           389: 
        !           390:        if (length)
        !           391:        {
        !           392:                ilength = 1/length;
        !           393:                v[0] *= ilength;
        !           394:                v[1] *= ilength;
        !           395:                v[2] *= ilength;
        !           396:        }
        !           397:                
        !           398:        return length;
        !           399: 
        !           400: }
        !           401: 
        !           402: void VectorInverse (vec3_t v)
        !           403: {
        !           404:        v[0] = -v[0];
        !           405:        v[1] = -v[1];
        !           406:        v[2] = -v[2];
        !           407: }
        !           408: 
        !           409: void VectorScale (vec3_t in, vec_t scale, vec3_t out)
        !           410: {
        !           411:        out[0] = in[0]*scale;
        !           412:        out[1] = in[1]*scale;
        !           413:        out[2] = in[2]*scale;
        !           414: }
        !           415: 
        !           416: 
        !           417: int Q_log2(int val)
        !           418: {
        !           419:        int answer=0;
        !           420:        while ((val>>=1) != 0)
        !           421:                answer++;
        !           422:        return answer;
        !           423: }
        !           424: 
        !           425: 
        !           426: /*
        !           427: ================
        !           428: R_ConcatRotations
        !           429: ================
        !           430: */
        !           431: void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
        !           432: {
        !           433:        out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
        !           434:                                in1[0][2] * in2[2][0];
        !           435:        out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
        !           436:                                in1[0][2] * in2[2][1];
        !           437:        out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
        !           438:                                in1[0][2] * in2[2][2];
        !           439:        out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
        !           440:                                in1[1][2] * in2[2][0];
        !           441:        out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
        !           442:                                in1[1][2] * in2[2][1];
        !           443:        out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
        !           444:                                in1[1][2] * in2[2][2];
        !           445:        out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
        !           446:                                in1[2][2] * in2[2][0];
        !           447:        out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
        !           448:                                in1[2][2] * in2[2][1];
        !           449:        out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
        !           450:                                in1[2][2] * in2[2][2];
        !           451: }
        !           452: 
        !           453: 
        !           454: /*
        !           455: ================
        !           456: R_ConcatTransforms
        !           457: ================
        !           458: */
        !           459: void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
        !           460: {
        !           461:        out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
        !           462:                                in1[0][2] * in2[2][0];
        !           463:        out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
        !           464:                                in1[0][2] * in2[2][1];
        !           465:        out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
        !           466:                                in1[0][2] * in2[2][2];
        !           467:        out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
        !           468:                                in1[0][2] * in2[2][3] + in1[0][3];
        !           469:        out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
        !           470:                                in1[1][2] * in2[2][0];
        !           471:        out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
        !           472:                                in1[1][2] * in2[2][1];
        !           473:        out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
        !           474:                                in1[1][2] * in2[2][2];
        !           475:        out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
        !           476:                                in1[1][2] * in2[2][3] + in1[1][3];
        !           477:        out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
        !           478:                                in1[2][2] * in2[2][0];
        !           479:        out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
        !           480:                                in1[2][2] * in2[2][1];
        !           481:        out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
        !           482:                                in1[2][2] * in2[2][2];
        !           483:        out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
        !           484:                                in1[2][2] * in2[2][3] + in1[2][3];
        !           485: }
        !           486: 
        !           487: 
        !           488: /*
        !           489: ===================
        !           490: FloorDivMod
        !           491: 
        !           492: Returns mathematically correct (floor-based) quotient and remainder for
        !           493: numer and denom, both of which should contain no fractional part. The
        !           494: quotient must fit in 32 bits.
        !           495: ====================
        !           496: */
        !           497: 
        !           498: void FloorDivMod (double numer, double denom, int *quotient,
        !           499:                int *rem)
        !           500: {
        !           501:        int             q, r;
        !           502:        double  x;
        !           503: 
        !           504: #ifndef PARANOID
        !           505:        if (denom <= 0.0)
        !           506:                Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
        !           507: 
        !           508: //     if ((floor(numer) != numer) || (floor(denom) != denom))
        !           509: //             Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
        !           510: //                             numer, denom);
        !           511: #endif
        !           512: 
        !           513:        if (numer >= 0.0)
        !           514:        {
        !           515: 
        !           516:                x = floor(numer / denom);
        !           517:                q = (int)x;
        !           518:                r = (int)floor(numer - (x * denom));
        !           519:        }
        !           520:        else
        !           521:        {
        !           522:        //
        !           523:        // perform operations with positive values, and fix mod to make floor-based
        !           524:        //
        !           525:                x = floor(-numer / denom);
        !           526:                q = -(int)x;
        !           527:                r = (int)floor(-numer - (x * denom));
        !           528:                if (r != 0)
        !           529:                {
        !           530:                        q--;
        !           531:                        r = (int)denom - r;
        !           532:                }
        !           533:        }
        !           534: 
        !           535:        *quotient = q;
        !           536:        *rem = r;
        !           537: }
        !           538: 
        !           539: 
        !           540: /*
        !           541: ===================
        !           542: GreatestCommonDivisor
        !           543: ====================
        !           544: */
        !           545: int GreatestCommonDivisor (int i1, int i2)
        !           546: {
        !           547:        if (i1 > i2)
        !           548:        {
        !           549:                if (i2 == 0)
        !           550:                        return (i1);
        !           551:                return GreatestCommonDivisor (i2, i1 % i2);
        !           552:        }
        !           553:        else
        !           554:        {
        !           555:                if (i1 == 0)
        !           556:                        return (i2);
        !           557:                return GreatestCommonDivisor (i1, i2 % i1);
        !           558:        }
        !           559: }
        !           560: 
        !           561: 
        !           562: #if !id386
        !           563: 
        !           564: // TODO: move to nonintel.c
        !           565: 
        !           566: /*
        !           567: ===================
        !           568: Invert24To16
        !           569: 
        !           570: Inverts an 8.24 value to a 16.16 value
        !           571: ====================
        !           572: */
        !           573: 
        !           574: fixed16_t Invert24To16(fixed16_t val)
        !           575: {
        !           576:        if (val < 256)
        !           577:                return (0xFFFFFFFF);
        !           578: 
        !           579:        return (fixed16_t)
        !           580:                        (((double)0x10000 * (double)0x1000000 / (double)val) + 0.5);
        !           581: }
        !           582: 
        !           583: #endif

unix.superglobalmegacorp.com

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