Annotation of researchv10dc/cmd/icon/src/iconx/oarith.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * File: oarith.c
        !             3:  *  Contents: div, minus, mod, mult, neg, number, plus, power
        !             4:  */
        !             5: 
        !             6: #include "../h/rt.h"
        !             7: #ifdef SUN
        !             8: #include <math.h>
        !             9: #include <signal.h>
        !            10: #endif SUN
        !            11: 
        !            12: #ifdef NoOver
        !            13: #define Add(x,y) (x + y)
        !            14: #define Sub(x,y) (x - y)
        !            15: #define Mpy(x,y) (x * y)
        !            16: #else NoOver
        !            17: #define Add(x,y) ckadd(x,y)
        !            18: #define Sub(x,y) cksub(x,y)
        !            19: #define Mpy(x,y) ckmul(x,y)
        !            20: #endif NoOver
        !            21: 
        !            22: /*
        !            23:  * x / y - divide y into x.
        !            24:  */
        !            25: 
        !            26: OpDcl(div,2,"/")
        !            27:    {
        !            28:    register int t1, t2;
        !            29:    union numeric n1, n2;
        !            30: 
        !            31:    /*
        !            32:     * x and y must be numbers.
        !            33:     */
        !            34:    if ((t1 = cvnum(&Arg1, &n1)) == NULL)
        !            35:       runerr(102, &Arg1);
        !            36:    if ((t2 = cvnum(&Arg2, &n2)) == NULL)
        !            37:       runerr(102, &Arg2);
        !            38: 
        !            39:    if (!(t1 == T_Real || t2 == T_Real)) {
        !            40:       /*
        !            41:        * x and y are both integers, just divide them and return the result.
        !            42:        */
        !            43:       if (n2.integer == 0L)
        !            44:          runerr(201, &Arg2);
        !            45:       Mkint(n1.integer / n2.integer, &Arg0);
        !            46:       }
        !            47:    else {
        !            48:       /*
        !            49:        * Either x or y or both is real, convert the real values to integers,
        !            50:        *  divide them, and return the result.
        !            51:        */
        !            52:       if (!(t1 == T_Real))
        !            53:          n1.real = n1.integer;
        !            54:       if (!(t2 == T_Real))
        !            55:          n2.real = n2.integer;
        !            56: #ifdef ZeroDivide
        !            57:       if (n2.real == 0.0)
        !            58:          runerr(204,0);
        !            59: #endif ZeroDivide
        !            60:       mkreal(n1.real / n2.real, &Arg0);
        !            61: #ifdef SUN
        !            62:       if (((struct b_real *)BlkLoc(Arg0))->realval == HUGE)
        !            63:          kill(getpid(),SIGFPE);
        !            64: #endif SUN
        !            65:       }
        !            66:    Return;
        !            67:    }
        !            68: 
        !            69: 
        !            70: /*
        !            71:  * x - y - subtract y from x.
        !            72:  */
        !            73: 
        !            74: OpDcl(minus,2,"-")
        !            75:    {
        !            76:    register int t1, t2;
        !            77:    union numeric n1, n2;
        !            78: #ifndef NoOver
        !            79:    extern long cksub();
        !            80: #endif NoOver
        !            81: 
        !            82:    /*
        !            83:     * x and y must be numeric.  Save the cvnum return values for later use.
        !            84:     */
        !            85:    if ((t1 = cvnum(&Arg1, &n1)) == NULL)
        !            86:       runerr(102, &Arg1);
        !            87:    if ((t2 = cvnum(&Arg2, &n2)) == NULL)
        !            88:       runerr(102, &Arg2);
        !            89: 
        !            90:    if (!(t1 == T_Real || t2 == T_Real)) {
        !            91:       /*
        !            92:        * Both x and y are integers.  Perform integer subtraction and place
        !            93:        *  the result in Arg0 as the return value.
        !            94:        */
        !            95:       Mkint(Sub(n1.integer, n2.integer), &Arg0);
        !            96:       }
        !            97:    else {
        !            98:       /*
        !            99:        * Either x or y is real, convert the other to a real, perform
        !           100:        *  the subtraction and place the result in Arg0 as the return value.
        !           101:        */
        !           102:       if (!(t1 == T_Real))
        !           103:          n1.real = n1.integer;
        !           104:       if (!(t2 == T_Real))
        !           105:          n2.real = n2.integer;
        !           106:       mkreal(n1.real - n2.real, &Arg0);
        !           107:       }
        !           108:    Return;
        !           109:    }
        !           110: 
        !           111: 
        !           112: /*
        !           113:  * x % y - take remainder of x / y.
        !           114:  */
        !           115: 
        !           116: OpDcl(mod,2,"%")
        !           117:    {
        !           118:    register int t1, t2;
        !           119:    union numeric n1, n2;
        !           120: 
        !           121:    /*
        !           122:     * x and y must be numeric.  Save the cvnum return values for later use.
        !           123:     */
        !           124:    if ((t1 = cvnum(&Arg1, &n1)) == NULL)
        !           125:       runerr(102, &Arg1);
        !           126:    if ((t2 = cvnum(&Arg2, &n2)) == NULL)
        !           127:       runerr(102, &Arg2);
        !           128: 
        !           129:    if (!(t1 == T_Real || t2 == T_Real)) {
        !           130:       /*
        !           131:        * Both x and y are integers.  If y is 0, generate an error because
        !           132:        *  it's divide by 0.  Otherwise, just return the modulus of the
        !           133:        *  two arguments.
        !           134:        */
        !           135:       if (n2.integer == 0L)
        !           136:          runerr(202, &Arg2);
        !           137:       Mkint(n1.integer % n2.integer, &Arg0);
        !           138:       }
        !           139:    else {
        !           140:       /*
        !           141:        * Either x or y is real, convert the other to a real, perform
        !           142:        *  the modulation, convert the result to an integer and place it
        !           143:        *  in Arg0 as the return value.
        !           144:        */
        !           145:       if (!(t1 == T_Real))
        !           146:          n1.real = n1.integer;
        !           147:       if (!(t2 == T_Real))
        !           148:          n2.real = n2.integer;
        !           149:       mkreal(n1.real - n2.real * (int)(n1.real / n2.real), &Arg0);
        !           150:       }
        !           151:    Return;
        !           152:    }
        !           153: 
        !           154: 
        !           155: /*
        !           156:  * x * y - multiply x and y.
        !           157:  */
        !           158: 
        !           159: OpDcl(mult,2,"*")
        !           160:    {
        !           161:    register int t1, t2;
        !           162:    union numeric n1, n2;
        !           163: #ifndef NoOver
        !           164:    extern long ckmul();
        !           165: #endif NoOver
        !           166: 
        !           167:    /*
        !           168:     * x and y must be numeric.  Save the cvnum return values for later use.
        !           169:     */
        !           170:    if ((t1 = cvnum(&Arg1, &n1)) == NULL)
        !           171:       runerr(102, &Arg1);
        !           172:    if ((t2 = cvnum(&Arg2, &n2)) == NULL)
        !           173:       runerr(102, &Arg2);
        !           174: 
        !           175:    if (!(t1 == T_Real || t2 == T_Real)) {
        !           176:       /*
        !           177:        * Both x and y are integers.  Perform the multiplication and
        !           178:        *  and place the result in Arg0 as the return value.
        !           179:        */
        !           180:       Mkint(Mpy(n1.integer,n2.integer), &Arg0);
        !           181:       }
        !           182:    else {
        !           183:       /*
        !           184:        * Either x or y is real, convert the other to a real, perform
        !           185:        *  the subtraction and place the result in Arg0 as the return value.
        !           186:        */
        !           187:       if (!(t1 == T_Real))
        !           188:          n1.real = n1.integer;
        !           189:       if (!(t2 == T_Real))
        !           190:          n2.real = n2.integer;
        !           191:       mkreal(n1.real * n2.real, &Arg0);
        !           192:       }
        !           193:    Return;
        !           194:    }
        !           195: 
        !           196: 
        !           197: /*
        !           198:  * -x - negate x.
        !           199:  */
        !           200: 
        !           201: OpDcl(neg,1,"-")
        !           202:    {
        !           203:    union numeric n;
        !           204:    long l;
        !           205: 
        !           206:    /*
        !           207:     * x must be numeric.
        !           208:     */
        !           209:    switch (cvnum(&Arg1, &n)) {
        !           210: 
        !           211:       case T_Integer:
        !           212:       case T_Longint:
        !           213:          /*
        !           214:           * If it's an integer, check for overflow by negating it and
        !           215:           *  seeing if the negation didn't "work".  Use Mkint to
        !           216:           *  construct the return value.
        !           217:           */
        !           218:          l = -n.integer;
        !           219:          if (n.integer < 0 && l < 0)
        !           220:             runerr(203, &Arg1);
        !           221:          Mkint(l, &Arg0);
        !           222:          break;
        !           223: 
        !           224:       case T_Real:
        !           225:          /*
        !           226:           * x is real, just negate it and use mkreal to construct the
        !           227:           *  return value.
        !           228:           */
        !           229:          mkreal(-n.real, &Arg0);
        !           230:          break;
        !           231: 
        !           232:       default:
        !           233:          /*
        !           234:           * x isn't numeric.
        !           235:           */
        !           236:          runerr(102, &Arg1);
        !           237:       }
        !           238:    Return;
        !           239:    }
        !           240: 
        !           241: 
        !           242: /*
        !           243:  * +x - convert x to numeric type.
        !           244:  *  Operational definition: generate runerr if x is not numeric.
        !           245:  */
        !           246: 
        !           247: OpDcl(number,1,"+")
        !           248:    {
        !           249:    union numeric n;
        !           250: 
        !           251:    switch (cvnum(&Arg1, &n)) {
        !           252: 
        !           253:       case T_Integer:
        !           254:       case T_Longint:
        !           255:          Mkint(n.integer, &Arg0);
        !           256:          break;
        !           257: 
        !           258:       case T_Real:
        !           259:          mkreal(n.real, &Arg0);
        !           260:          break;
        !           261: 
        !           262:       default:
        !           263:          runerr(102, &Arg1);
        !           264:       }
        !           265:    Return;
        !           266:    }
        !           267: 
        !           268: 
        !           269: /*
        !           270:  * x + y - add x and y.
        !           271:  */
        !           272: 
        !           273: OpDcl(plus,2,"+")
        !           274:    {
        !           275:    register int t1, t2;
        !           276:    union numeric n1, n2;
        !           277: #ifndef NoOver
        !           278:    extern long ckadd();
        !           279: #endif NoOver
        !           280: 
        !           281:    /*
        !           282:     * x and y must be numeric.  Save the cvnum return values for later use.
        !           283:     */
        !           284:    if ((t1 = cvnum(&Arg1, &n1)) == NULL)
        !           285:       runerr(102, &Arg1);
        !           286:    if ((t2 = cvnum(&Arg2, &n2)) == NULL)
        !           287:       runerr(102, &Arg2);
        !           288: 
        !           289:    if (!(t1 == T_Real || t2 == T_Real)) {
        !           290:       /*
        !           291:        * Both x and y are integers.  Perform integer addition and plcae the
        !           292:        *  result in Arg0 as the return value.
        !           293:        */
        !           294:       Mkint(Add(n1.integer, n2.integer), &Arg0);
        !           295:       }
        !           296:    else {
        !           297:       /*
        !           298:        * Either x or y is real, convert the other to a real, perform
        !           299:        *  the addition and place the result in Arg0 as the return value.
        !           300:        */
        !           301:       if (!(t1 == T_Real))
        !           302:          n1.real = n1.integer;
        !           303:       if (!(t2 == T_Real))
        !           304:          n2.real = n2.integer;
        !           305:       mkreal(n1.real + n2.real, &Arg0);
        !           306:       }
        !           307:    Return;
        !           308:    }
        !           309: 
        !           310: 
        !           311: 
        !           312: 
        !           313: /*
        !           314:  * x ^ y - raise x to the y power.
        !           315:  */
        !           316: 
        !           317: OpDcl(power,2,"^")
        !           318:    {
        !           319:    register int t1, t2;
        !           320:    union numeric n1, n2;
        !           321:    extern double pow();
        !           322:    extern long ipow();
        !           323: 
        !           324:    /*
        !           325:     * x and y must be numeric.  Save the cvnum return values for later use.
        !           326:     */
        !           327:    if ((t1 = cvnum(&Arg1, &n1)) == NULL)
        !           328:       runerr(102, &Arg1);
        !           329:    if ((t2 = cvnum(&Arg2, &n2)) == NULL)
        !           330:       runerr(102, &Arg2);
        !           331: 
        !           332:    if (!(t1 == T_Real || t2 == T_Real)) {
        !           333:       /*
        !           334:        * Both x and y are integers.  Perform integer exponentiation
        !           335:        *  and place the result in Arg0 as the return value.
        !           336:        */
        !           337:       Mkint(ipow(n1.integer, n2.integer), &Arg0);
        !           338:       }
        !           339:    else {
        !           340:       /*
        !           341:        * Either x or y is real, convert the other to a real, perform
        !           342:        *  real exponentiation and place the result in Arg0 as the
        !           343:        *  return value.
        !           344:        */
        !           345:       if (!(t1 == T_Real))
        !           346:          n1.real = n1.integer;
        !           347:       if (!(t2 == T_Real))
        !           348:          n2.real = n2.integer;
        !           349:       if (n1.real == 0.0 && n2.real <= 0.0)
        !           350:          /*
        !           351:           * Tried to raise zero to a negative power.
        !           352:           */
        !           353:          runerr(204, NULL);
        !           354:       if (n1.real < 0.0 && t2 == T_Real)
        !           355:          /*
        !           356:           * Tried to raise a negative number to a real power.
        !           357:           */
        !           358:          runerr(206, NULL);
        !           359:       mkreal(pow(n1.real,n2.real), &Arg0);
        !           360:       }
        !           361:    Return;
        !           362:    }
        !           363: 
        !           364: long ipow(n1, n2)
        !           365: long n1, n2;
        !           366:    {
        !           367:    long result;
        !           368: 
        !           369:    if (n1 == 0 && n2 <= 0)
        !           370:       runerr(204, NULL);
        !           371:    if (n2 < 0)
        !           372:       return 0.0;
        !           373:    result = 1L;
        !           374:    while (n2 > 0) {
        !           375:       if (n2 & 01L)
        !           376:          result *= n1;
        !           377:       n1 *= n1;
        !           378:       n2 >>= 1;
        !           379:       }
        !           380:    return result;
        !           381:    }

unix.superglobalmegacorp.com

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