gt: 			distance.add(new VarInsnNode(Opcodes.DSTORE, numVariable));
context: /**
   * Copyright (C) 2010-2015 Gordon Fraser, Andrea Arcuri and EvoSuite
   * contributors
   *
   * This file is part of EvoSuite.
   *
   * EvoSuite is free software: you can redistribute it and/or modify it
   * under the terms of the GNU Lesser Public License as published by the
   * Free Software Foundation, either version 3.0 of the License, or (at your
   * option) any later version.
   *
   * EvoSuite is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * Lesser Public License for more details.
   *
   * You should have received a copy of the GNU Lesser Public License along
   * with EvoSuite. If not, see <http://www.gnu.org/licenses/>.
   */
  /**
   * 
   */
  package org.evosuite.instrumentation.mutation;
  
  import java.util.Arrays;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Set;
  
  import org.evosuite.coverage.mutation.Mutation;
  import org.evosuite.coverage.mutation.MutationPool;
  import org.evosuite.graphs.cfg.BytecodeInstruction;
  import org.objectweb.asm.Opcodes;
  import org.objectweb.asm.Type;
  import org.objectweb.asm.tree.AbstractInsnNode;
  import org.objectweb.asm.tree.InsnList;
  import org.objectweb.asm.tree.InsnNode;
  import org.objectweb.asm.tree.LdcInsnNode;
  import org.objectweb.asm.tree.LocalVariableNode;
  import org.objectweb.asm.tree.MethodInsnNode;
  import org.objectweb.asm.tree.MethodNode;
  import org.objectweb.asm.tree.VarInsnNode;
  import org.objectweb.asm.tree.analysis.Frame;
  
  
  /**
   * <p>ReplaceArithmeticOperator class.</p>
   *
   * @author Gordon Fraser
   */
  public class ReplaceArithmeticOperator implements MutationOperator {
  
  	private static Set<Integer> opcodesInt = new HashSet<Integer>();
  
  	private static Set<Integer> opcodesLong = new HashSet<Integer>();
  
  	private static Set<Integer> opcodesFloat = new HashSet<Integer>();
  
  	private static Set<Integer> opcodesDouble = new HashSet<Integer>();
  
  	private int numVariable = 0;
  
  	static {
  		opcodesInt.addAll(Arrays.asList(new Integer[] { Opcodes.IADD, Opcodes.ISUB,
  		        Opcodes.IMUL, Opcodes.IDIV, Opcodes.IREM }));
  
  		opcodesLong.addAll(Arrays.asList(new Integer[] { Opcodes.LADD, Opcodes.LSUB,
  		        Opcodes.LMUL, Opcodes.LDIV, Opcodes.LREM }));
  
  		opcodesFloat.addAll(Arrays.asList(new Integer[] { Opcodes.FADD, Opcodes.FSUB,
  		        Opcodes.FMUL, Opcodes.FDIV, Opcodes.FREM }));
  
  		opcodesDouble.addAll(Arrays.asList(new Integer[] { Opcodes.DADD, Opcodes.DSUB,
  		        Opcodes.DMUL, Opcodes.DDIV, Opcodes.DREM }));
  	}
  
  	private String getOp(int opcode) {
  		switch (opcode) {
  		case Opcodes.IADD:
  		case Opcodes.LADD:
  		case Opcodes.FADD:
  		case Opcodes.DADD:
  			return "+";
  		case Opcodes.ISUB:
  		case Opcodes.LSUB:
  		case Opcodes.FSUB:
  		case Opcodes.DSUB:
  			return "-";
  		case Opcodes.IMUL:
  		case Opcodes.LMUL:
  		case Opcodes.FMUL:
  		case Opcodes.DMUL:
  			return "*";
  		case Opcodes.IDIV:
  		case Opcodes.LDIV:
  		case Opcodes.FDIV:
  		case Opcodes.DDIV:
  			return "/";
  		case Opcodes.IREM:
  		case Opcodes.LREM:
  		case Opcodes.FREM:
  		case Opcodes.DREM:
  			return "%";
  		}
  		throw new RuntimeException("Unknown opcode: " + opcode);
  	}
  
  	/**
  	 * <p>getNextIndex</p>
  	 *
  	 * @param mn a {@link org.objectweb.asm.tree.MethodNode} object.
  	 * @return a int.
  	 */
  	@SuppressWarnings("rawtypes")
  	public static int getNextIndex(MethodNode mn) {
  		Iterator it = mn.localVariables.iterator();
  		int max = 0;
  		int next = 0;
  		while (it.hasNext()) {
  			LocalVariableNode var = (LocalVariableNode) it.next();
  			int index = var.index;
  			if (index >= max) {
  				max = index;
  				next = max + Type.getType(var.desc).getSize();
  			}
  		}
  		if (next == 0)
  			next = getNextIndexFromLoad(mn);
  		return next;
  	}
  
  	@SuppressWarnings("rawtypes")
  	private static int getNextIndexFromLoad(MethodNode mn) {
  		Iterator it = mn.instructions.iterator();
  		int index = 0;
  		while (it.hasNext()) {
  			AbstractInsnNode node = (AbstractInsnNode) it.next();
  			if (node instanceof VarInsnNode) {
  				VarInsnNode varNode = (VarInsnNode) node;
  				int varIndex = varNode.var;
  				switch (varNode.getOpcode()) {
  				case Opcodes.ALOAD:
  				case Opcodes.ILOAD:
  				case Opcodes.FLOAD:
  				case Opcodes.IALOAD:
  				case Opcodes.BALOAD:
  				case Opcodes.CALOAD:
  				case Opcodes.AALOAD:
  				case Opcodes.ASTORE:
  				case Opcodes.ISTORE:
  				case Opcodes.FSTORE:
  				case Opcodes.IASTORE:
  				case Opcodes.BASTORE:
  				case Opcodes.CASTORE:
  				case Opcodes.AASTORE:
  					index = Math.max(index, varIndex + 1);
  					break;
  				case Opcodes.DLOAD:
  				case Opcodes.DSTORE:
  				case Opcodes.LLOAD:
  				case Opcodes.LSTORE:
  				case Opcodes.DALOAD:
  				case Opcodes.DASTORE:
  				case Opcodes.LALOAD:
  				case Opcodes.LASTORE:
  					index = Math.max(index, varIndex + 2);
  					break;
  				}
  			}
  		}
  
  		return index;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.evosuite.cfg.instrumentation.MutationOperator#apply(org.objectweb.asm.tree.MethodNode, java.lang.String, java.lang.String, org.evosuite.cfg.BytecodeInstruction)
  	 */
  	/** {@inheritDoc} */
  	@Override
  	public List<Mutation> apply(MethodNode mn, String className, String methodName,
  	        BytecodeInstruction instruction, Frame frame) {
  
  		numVariable = getNextIndex(mn);
  		List<Mutation> mutations = new LinkedList<Mutation>();
  
  		InsnNode node = (InsnNode) instruction.getASMNode();
  
  		for (int opcode : getMutations(node.getOpcode())) {
  
  			InsnNode mutation = new InsnNode(opcode);
  			// insert mutation into pool
  			Mutation mutationObject = MutationPool.addMutation(className,
  			                                                   methodName,
  			                                                   "ReplaceArithmeticOperator "
  			                                                           + getOp(node.getOpcode())
  			                                                           + " -> "
  			                                                           + getOp(opcode),
  			                                                   instruction,
  			                                                   mutation,
  			                                                   getInfectionDistance(node.getOpcode(),
  			                                                                        opcode));
  			mutations.add(mutationObject);
  		}
  
  		return mutations;
  	}
  
  	private Set<Integer> getMutations(int opcode) {
  		Set<Integer> replacement = new HashSet<Integer>();
  		if (opcodesInt.contains(opcode))
  			replacement.addAll(opcodesInt);
  		else if (opcodesLong.contains(opcode))
  			replacement.addAll(opcodesLong);
  		else if (opcodesFloat.contains(opcode))
  			replacement.addAll(opcodesFloat);
  		else if (opcodesDouble.contains(opcode))
  			replacement.addAll(opcodesDouble);
  
  		replacement.remove(opcode);
  		return replacement;
  	}
  
  	/**
  	 * <p>getInfectionDistance</p>
  	 *
  	 * @param opcodeOrig a int.
  	 * @param opcodeNew a int.
  	 * @return a {@link org.objectweb.asm.tree.InsnList} object.
  	 */
  	public InsnList getInfectionDistance(int opcodeOrig, int opcodeNew) {
  		InsnList distance = new InsnList();
  
  		if (opcodesInt.contains(opcodeOrig)) {
  			distance.add(new InsnNode(Opcodes.DUP2));
  			distance.add(new LdcInsnNode(opcodeOrig));
  			distance.add(new LdcInsnNode(opcodeNew));
  			distance.add(new MethodInsnNode(
  			        Opcodes.INVOKESTATIC,
  			        "org/evosuite/instrumentation/mutation/ReplaceArithmeticOperator",
  			        "getInfectionDistanceInt", "(IIII)D", false));
  		} else if (opcodesLong.contains(opcodeOrig)) {
  			distance.add(new VarInsnNode(Opcodes.LSTORE, numVariable));
  			distance.add(new InsnNode(Opcodes.DUP2));
  			distance.add(new VarInsnNode(Opcodes.LLOAD, numVariable));
  			distance.add(new InsnNode(Opcodes.DUP2_X2));
  			distance.add(new LdcInsnNode(opcodeOrig));
  			distance.add(new LdcInsnNode(opcodeNew));
  			distance.add(new MethodInsnNode(
  			        Opcodes.INVOKESTATIC,
  			        "org/evosuite/instrumentation/mutation/ReplaceArithmeticOperator",
  			        "getInfectionDistanceLong", "(JJII)D", false));
  			numVariable += 2;
  		} else if (opcodesFloat.contains(opcodeOrig)) {
  			distance.add(new InsnNode(Opcodes.DUP2));
  			distance.add(new LdcInsnNode(opcodeOrig));
  			distance.add(new LdcInsnNode(opcodeNew));
  			distance.add(new MethodInsnNode(
  			        Opcodes.INVOKESTATIC,
  			        "org/evosuite/instrumentation/mutation/ReplaceArithmeticOperator",
  			        "getInfectionDistanceFloat", "(FFII)D", false));
  		} else if (opcodesDouble.contains(opcodeOrig)) {
  