Annotation of researchv10dc/cmd/icon/src/iconx/oarith.c, revision 1.1.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.