|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.