/**
  * Creates a partial mapping.
  *
  * <p>Initially, no element is mapped to any other:
  *
  * <table border="1">
  * <caption>Example</caption>
  * <tr>
  * <th>source</th>
  * <td>0</td>
  * <td>1</td>
  * <td>2</td>
  * </tr>
  * <tr>
  * <th>target</th>
  * <td>-1</td>
  * <td>-1</td>
  * <td>-1</td>
  * </tr>
  * </table>
  *
  * <table border="1">
  * <caption>Example</caption>
  * <tr>
  * <th>target</th>
  * <td>0</td>
  * <td>1</td>
  * <td>2</td>
  * <td>3</td>
  * </tr>
  * <tr>
  * <th>source</th>
  * <td>-1</td>
  * <td>-1</td>
  * <td>-1</td>
  * <td>-1</td>
  * </tr>
  * </table>
  *
  * @param sourceCount Number of source elements
  * @param targetCount Number of target elements
  * @param mappingType Mapping type; must not allow multiple sources per target or multiple
  *     targets per source
  */
 public PartialMapping(int sourceCount, int targetCount, MappingType mappingType) {
   this.mappingType = mappingType;
   assert mappingType.isSingleSource() : mappingType;
   assert mappingType.isSingleTarget() : mappingType;
   this.sources = new int[targetCount];
   this.targets = new int[sourceCount];
   Arrays.fill(sources, -1);
   Arrays.fill(targets, -1);
 }
 /**
  * Creates a partial mapping from a list. For example, <code>
  * PartialMapping({1, 2, 4}, 6)</code> creates the mapping
  *
  * <table border="1">
  * <caption>Example</caption>
  * <tr>
  * <th>source</th>
  * <td>0</td>
  * <td>1</td>
  * <td>2</td>
  * <td>3</td>
  * <td>4</td>
  * <td>5</td>
  * </tr>
  * <tr>
  * <th>target</th>
  * <td>-1</td>
  * <td>0</td>
  * <td>1</td>
  * <td>-1</td>
  * <td>2</td>
  * <td>-1</td>
  * </tr>
  * </table>
  *
  * @param sourceList List whose i'th element is the source of target #i
  * @param sourceCount Number of elements in the source domain
  * @param mappingType Mapping type, must be {@link
  *     org.eigenbase.util.mapping.MappingType#PARTIAL_SURJECTION} or stronger.
  */
 public PartialMapping(List<Integer> sourceList, int sourceCount, MappingType mappingType) {
   this.mappingType = mappingType;
   assert mappingType.isSingleSource();
   assert mappingType.isSingleTarget();
   int targetCount = sourceList.size();
   this.targets = new int[sourceCount];
   this.sources = new int[targetCount];
   Arrays.fill(sources, -1);
   for (int i = 0; i < sourceList.size(); ++i) {
     final int source = sourceList.get(i);
     sources[i] = source;
     if (source >= 0) {
       targets[source] = i;
     } else {
       assert !this.mappingType.isMandatorySource();
     }
   }
 }
 public void set(int source, int target) {
   if ((target < 0) && mappingType.isMandatorySource()) {
     throw new IllegalArgumentException("Target is required");
   }
   if ((target >= targetCount) && (targetCount >= 0)) {
     throw new IllegalArgumentException("Target must be less than target count, " + targetCount);
   }
   targets[source] = target;
 }
 public PartialFunctionImpl(int sourceCount, int targetCount, MappingType mappingType) {
   super();
   if (sourceCount < 0) {
     throw new IllegalArgumentException("Sources must be finite");
   }
   this.sourceCount = sourceCount;
   this.targetCount = targetCount;
   this.mappingType = mappingType;
   if (!mappingType.isSingleTarget()) {
     throw new IllegalArgumentException("Must have at most one target");
   }
   this.targets = new int[sourceCount];
   Arrays.fill(targets, -1);
 }
 /** Creates a mapping with required properties. */
 public static Mapping create(MappingType mappingType, int sourceCount, int targetCount) {
   switch (mappingType) {
     case BIJECTION:
       assert sourceCount == targetCount;
       return new Permutation(sourceCount);
     case INVERSE_SURJECTION:
       assert sourceCount >= targetCount;
       return new SurjectionWithInverse(sourceCount, targetCount);
     case PARTIAL_SURJECTION:
     case SURJECTION:
       return new Mappings.PartialMapping(sourceCount, targetCount, mappingType);
     case PARTIAL_FUNCTION:
     case FUNCTION:
       return new PartialFunctionImpl(sourceCount, targetCount, mappingType);
     case INVERSE_FUNCTION:
     case INVERSE_PARTIAL_FUNCTION:
       return new InverseMapping(create(mappingType.inverse(), targetCount, sourceCount));
     default:
       throw Util.needToImplement("no known implementation for mapping type " + mappingType);
   }
 }
 public Mapping inverse() {
   return new PartialMapping(targets.clone(), sources.clone(), mappingType.inverse());
 }