1 4 package gnu.kawa.functions; 5 import gnu.math.*; 6 import java.math.*; 7 import gnu.mapping.*; 8 import gnu.expr.*; 9 import gnu.bytecode.*; 10 import gnu.kawa.lispexpr.LangPrimType; 11 12 16 17 public class AddOp extends ProcedureN implements CanInline, Inlineable 18 { 19 int plusOrMinus = 1; 20 21 public AddOp(String name, int plusOrMinus) 22 { 23 setName(name); 24 this.plusOrMinus = plusOrMinus; 25 } 26 27 public static final AddOp $Pl = new AddOp("+", 1); 28 public static final AddOp $Mn = new AddOp("-", -1); 29 30 public static Object apply2(int plusOrMinus, Object arg1, Object arg2) 31 { 32 int code1 = Arithmetic.classifyValue(arg1); 33 int code2 = Arithmetic.classifyValue(arg2); 34 38 int code = code1 < code2 ? code2 : code1; 39 switch (code) 40 { 41 case Arithmetic.INT_CODE: 42 int i1 = Arithmetic.asInt(arg1); 43 int i2 = Arithmetic.asInt(arg2); 44 return new Integer (plusOrMinus > 0 ? i1 + i2 : i1 - i2); 45 case Arithmetic.LONG_CODE: 46 long l1 = Arithmetic.asLong(arg1); 47 long l2 = Arithmetic.asLong(arg2); 48 return new Long (plusOrMinus > 0 ? l1 + l2 : l1 - l2); 49 case Arithmetic.BIGINTEGER_CODE: 50 BigInteger bi1 = Arithmetic.asBigInteger(arg1); 51 BigInteger bi2 = Arithmetic.asBigInteger(arg2); 52 return plusOrMinus > 0 ? bi1.add(bi2) : bi1.subtract(bi2); 53 case Arithmetic.INTNUM_CODE: 54 return IntNum.add(Arithmetic.asIntNum(arg1), Arithmetic.asIntNum(arg2), 55 plusOrMinus); 56 case Arithmetic.BIGDECIMAL_CODE: 57 BigDecimal bd1 = Arithmetic.asBigDecimal(arg1); 58 BigDecimal bd2 = Arithmetic.asBigDecimal(arg2); 59 return plusOrMinus > 0 ? bd1.add(bd2) : bd1.subtract(bd2); 60 case Arithmetic.RATNUM_CODE: 61 return RatNum.add(Arithmetic.asRatNum(arg1), Arithmetic.asRatNum(arg2), 62 plusOrMinus); 63 case Arithmetic.FLOAT_CODE: 64 float f1 = Arithmetic.asFloat(arg1); 65 float f2 = Arithmetic.asFloat(arg2); 66 return new Float (plusOrMinus > 0 ? f1 + f2 : f1 - f2); 67 case Arithmetic.DOUBLE_CODE: 68 double d1 = Arithmetic.asDouble(arg1); 69 double d2 = Arithmetic.asDouble(arg2); 70 return new Double (plusOrMinus > 0 ? d1 + d2 : d1 - d2); 71 case Arithmetic.FLONUM_CODE: 72 d1 = Arithmetic.asDouble(arg1); 73 d2 = Arithmetic.asDouble(arg2); 74 return new DFloNum(plusOrMinus > 0 ? d1 + d2 : d1 - d2); 75 default: 76 Numeric num1 = Arithmetic.asNumeric(arg1); 77 Numeric num2 = Arithmetic.asNumeric(arg2); 78 return num1.add(num2, plusOrMinus); 79 } 80 } 81 82 public static Object $Pl(Object arg1, Object arg2) 83 { 84 return apply2(1, arg1, arg2); 85 } 86 87 public static Object $Mn(Object arg1, Object arg2) 88 { 89 return apply2(-1, arg1, arg2); 90 } 91 92 public static Object $Mn(Object arg1) 93 { 94 return ((Numeric) arg1).neg(); 95 } 96 97 public static Object $Pl$V (Object arg1, Object arg2, 98 Object arg3, Object [] rest) 99 { 100 return applyN(1, apply2(1,apply2(1, arg1, arg2), arg3), rest); 101 } 102 103 public static Object $Mn$V (Object arg1, Object arg2, 104 Object arg3, Object [] rest) 105 { 106 return applyN(-1, apply2(-1,apply2(-1, arg1, arg2), arg3), rest); 107 } 108 109 public static Object applyN(int plusOrMinus, Object [] args) 110 { 111 int len = args.length; 112 if (len == 0) 113 return IntNum.zero (); 114 Object result = args[0]; 115 if (len == 1 && plusOrMinus < 0) 116 return $Mn(result); 117 for (int i = 1; i < len; i++) 118 result = apply2(plusOrMinus, result, args[i]); 119 return result; 120 } 121 122 public static Object applyN(int plusOrMinus, Object init, Object [] args) 123 { 124 int len = args.length; 125 Object result = init; 126 for (int i = 0; i < len; i++) 127 result = apply2(plusOrMinus, result, args[i]); 128 return result; 129 } 130 131 public Object applyN (Object [] args) 132 { 133 return applyN(plusOrMinus, args); 134 } 135 136 137 138 public static Expression pairwise(Procedure proc, 139 Expression rproc, Expression[] args, 140 ExpWalker walker) 141 { 142 int len = args.length; 143 Expression prev = args[0]; 144 for (int i = 1; i < len; i++) 145 { 146 Expression[] args2 = new Expression[2]; 147 args2[0] = prev; 148 args2[1] = args[i]; 149 ApplyExp next = new ApplyExp(rproc, args2); 150 if (proc instanceof CanInline) 151 prev = ((CanInline) proc).inline(next, walker); 152 else 153 prev = next; 154 } 155 return prev; 156 } 157 158 public Expression inline (ApplyExp exp, ExpWalker walker) 159 { 160 if (! walker.getCompilation().mustCompile) 163 return exp; 164 Expression folded = exp.inlineIfConstant(this, walker); 165 if (folded != exp) 166 return folded; 167 Expression[] args = exp.getArgs(); 168 if (args.length > 2) 169 return pairwise(this, exp.getFunction(), args, walker); 170 if (args.length == 1 && plusOrMinus < 0) 171 { 172 Type type0 = args[0].getType(); 173 if (type0 instanceof PrimType) 174 { 175 char sig0 = type0.getSignature().charAt(0); 176 Type type = null; 177 int opcode = 0; 178 if (sig0 == 'V' || sig0 == 'Z' || sig0 == 'C') 179 { 180 } 182 else if (sig0 == 'D') 183 { 184 opcode = 119 ; 185 type = LangPrimType.doubleType; 186 } 187 else if (sig0 == 'F') 188 { 189 opcode = 118 ; 190 type = LangPrimType.floatType; 191 } 192 else if (sig0 == 'J') 193 { 194 opcode = 117 ; 195 type = LangPrimType.longType; 196 } 197 else 198 { 199 opcode = 116 ; 200 type = LangPrimType.intType; 201 } 202 if (type != null) 203 { 204 PrimProcedure prim 205 = PrimProcedure.makeBuiltinUnary(opcode, type); 206 return new ApplyExp(prim, args); 207 } 208 } 209 } 210 if (args.length == 2) 211 { 212 return primInline(plusOrMinus > 0 ? 96 : 100 , 213 exp); 214 } 215 return exp; 216 } 217 218 public static Expression primInline (int opcode, ApplyExp exp) 219 { 220 Expression[] args = exp.getArgs(); 221 if (args.length == 2) 222 { 223 Type type0 = args[0].getType(); 224 Type type1 = args[1].getType(); 225 if (type0 instanceof PrimType && type1 instanceof PrimType) 226 { 227 char sig0 = type0.getSignature().charAt(0); 228 char sig1 = type1.getSignature().charAt(0); 229 Type type = null; 230 if (sig0 == 'V' || sig0 == 'Z' || sig0 == 'C' 231 || sig1 == 'V' || sig1 == 'Z' || sig1 == 'C') 232 { 233 } 235 else if (sig0 == 'D' || sig1 == 'D') 236 { 237 opcode += 3; 238 type = LangPrimType.doubleType; 239 } 240 else if (sig0 == 'F' || sig1 == 'F') 241 { 242 opcode += 2; 243 type = LangPrimType.floatType; 244 } 245 else if (sig0 == 'J' || sig1 == 'J') 246 { 247 opcode += 1; 248 type = LangPrimType.longType; 249 } 250 else 251 { 252 type = LangPrimType.intType; 253 } 254 if (type != null) 255 { 256 PrimProcedure prim 257 = PrimProcedure.makeBuiltinBinary(opcode, type); 258 return new ApplyExp(prim, args); 259 } 260 } 261 } 262 return exp; 263 } 264 265 269 static ClassType typeIntNum = ClassType.make("gnu.math.IntNum"); 270 static ClassType typeDFloNum = ClassType.make("gnu.math.DFloNum"); 271 static ClassType typeRealNum = ClassType.make("gnu.math.RealNum"); 272 static ClassType typeNumeric = ClassType.make("gnu.math.Numeric"); 273 274 public void compile (ApplyExp exp, Compilation comp, Target target) 275 { 276 Expression[] args = exp.getArgs(); 277 int len = args.length; 278 if (len == 0) 279 { 280 comp.compileConstant(IntNum.zero(), target); 281 return; 282 } 283 Type type = getReturnType(args); 284 Type ttype = target.getType(); 285 if (len == 1 || target instanceof IgnoreTarget) 286 { 287 ApplyExp.compile(exp, comp, target); 289 return; 290 } 291 PrimType ptype = null; 292 if (ttype instanceof PrimType) 293 { 294 char sig = type.getSignature().charAt(0); 295 if (sig == 'V' || sig == 'Z' || sig == 'C') 296 ptype = null; else if (sig == 'D' || sig == 'F') 298 { 299 if (type.isSubtype(typeRealNum)) 300 ptype = LangPrimType.doubleType; 301 } 302 else 303 { 304 if (type.isSubtype(typeIntNum)) 305 ptype = sig == 'J' ? LangPrimType.longType : LangPrimType.intType; 306 } 307 } 308 if (ptype != null) 309 { 310 CodeAttr code = comp.getCode(); 311 args[0].compile(comp, ttype); 319 for (int i = 1; i < len; i++) 320 { 321 args[i].compile(comp, ptype); 322 if (plusOrMinus > 0) 323 code.emitAdd(ptype); 324 else 325 code.emitSub(ptype); 326 } 327 target.compileFromStack(comp, ttype); 328 } 329 else if (type.isSubtype(typeDFloNum)) 330 { 331 PrimType dtype = LangPrimType.doubleType; 332 Target dtarget = new StackTarget(dtype); 333 CodeAttr code = comp.getCode(); 334 args[0].compile(comp, dtarget); 335 for (int i = 1; i < len; i++) 336 { 337 args[i].compile(comp, dtarget); 338 if (plusOrMinus > 0) 339 code.emitAdd(dtype); 340 else 341 code.emitSub(dtype); 342 } 343 target.compileFromStack(comp, dtype); 344 } 345 else 346 ApplyExp.compile(exp, comp, target); 347 } 348 349 356 public static int classify (Type type) 357 { 358 int kind = 0; 359 if (type instanceof PrimType) 360 { 361 char sig = type.getSignature().charAt(0); 362 if (sig == 'V' || sig == 'Z' || sig == 'C') 363 return 0; 364 else if (sig == 'D' || sig == 'F') 365 return 3; 366 else 367 return 4; 368 } 369 else if (type.isSubtype(typeIntNum)) 370 return 4; 371 else if (type.isSubtype(typeDFloNum)) 372 return 3; 373 else if (type.isSubtype(typeRealNum)) 374 return 2; 375 else if (type.isSubtype(typeNumeric)) 376 return 1; 377 else 378 return 0; 379 } 380 381 public Type getReturnType (Expression[] args) 382 { 383 int len = args.length; 384 if (len == 0) 385 return typeIntNum; 386 Type type = Type.pointer_type; 387 int kind0 = 0; 388 for (int i = 0; i < len; i++) 389 { 390 Expression arg = args[i]; 391 int kind = classify(arg.getType()); 392 393 if (kind == 0) 394 return Type.pointer_type; 395 396 if (i == 0) 397 kind0 = kind; 398 399 if (kind0 == 4 && kind == 4) 400 type = typeIntNum; 401 else if (kind0 >= 2 && kind >= 2) 402 { 403 if (kind0 == 3 || kind == 3) 404 { 405 type = typeDFloNum; 406 kind0 = 3; 407 } 408 else 409 { 410 type = typeRealNum; 411 kind0 = 2; 412 } 413 } 414 else if (kind0 >= 1 && kind >= 1) 415 { 416 type = typeNumeric; 417 kind0 = 1; 418 } 419 else 420 return Type.pointer_type; 421 } 422 return type; 423 } 424 } 425 | Popular Tags |