// Path: combinatorics/src/main/java/com/xiantrimble/combinatorics/Utils.java
// @SuppressWarnings("unchecked")
// public static final <T> Class<T> getComponentType(final T[] array) {
//   return (Class<T>)array.getClass().getComponentType();
// }


import java.lang.reflect.Array;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import static com.xiantrimble.combinatorics.Utils.getComponentType;
/**
 * Copyright (C) 2012 Christian Trimble (xiantrimble@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xiantrimble.combinatorics;



/**
 * An abstract base class for combinatoric implementations.
 * 
 * @author Christian Trimble
 *
 * @param <T> the type of the elements being combined or permuted.
 */
public abstract class AbstractCombinatoric<T> extends AbstractList<T[]>
    implements Combinatoric<T> {

  /** The length of each result. */
  protected int k;
  /** The domain being operated on. */
  protected GroupedDomain<T> domain;
  /** A view of the domain as a 2-dimensional array for fast lookups. */
  protected T[][] domainValues;
  /** A view of the domain multiplicity. */
  protected int[] domainMultiplicity;
  /** The length of this collection. */
  protected long size;
  /** The math utilities used to compute the length. */
  protected CombMathUtils mathUtils;
  /** The component type for the arrays that will be returned. */
  protected Class<T> componentType;

  /**
   * @param k the length of the results.
   * @param domain the domain being operated on.
   * @param mathUtils the math utilities class used to compute the size of this collection.
   */
  protected AbstractCombinatoric(int k, T[] domain, CombMathUtils mathUtils) {
    this.k = k;
    this.domain = new FastGroupedDomain<T>(k, domain);
    this.mathUtils = mathUtils;
    this.size = computeSize(this.k, this.domain);
// Path: combinatorics/src/main/java/com/xiantrimble/combinatorics/Utils.java
// @SuppressWarnings("unchecked")
// public static final <T> Class<T> getComponentType(final T[] array) {
//   return (Class<T>)array.getClass().getComponentType();
// }


// Path: combinatorics/src/main/java/com/xiantrimble/combinatorics/AbstractCombinatoric.java
import java.lang.reflect.Array;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import static com.xiantrimble.combinatorics.Utils.getComponentType;

/**
 * Copyright (C) 2012 Christian Trimble (xiantrimble@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xiantrimble.combinatorics;



/**
 * An abstract base class for combinatoric implementations.
 * 
 * @author Christian Trimble
 *
 * @param <T> the type of the elements being combined or permuted.
 */
public abstract class AbstractCombinatoric<T> extends AbstractList<T[]>
    implements Combinatoric<T> {

  /** The length of each result. */
  protected int k;
  /** The domain being operated on. */
  protected GroupedDomain<T> domain;
  /** A view of the domain as a 2-dimensional array for fast lookups. */
  protected T[][] domainValues;
  /** A view of the domain multiplicity. */
  protected int[] domainMultiplicity;
  /** The length of this collection. */
  protected long size;
  /** The math utilities used to compute the length. */
  protected CombMathUtils mathUtils;
  /** The component type for the arrays that will be returned. */
  protected Class<T> componentType;

  /**
   * @param k the length of the results.
   * @param domain the domain being operated on.
   * @param mathUtils the math utilities class used to compute the size of this collection.
   */
  protected AbstractCombinatoric(int k, T[] domain, CombMathUtils mathUtils) {
    this.k = k;
    this.domain = new FastGroupedDomain<T>(k, domain);
    this.mathUtils = mathUtils;
    this.size = computeSize(this.k, this.domain);
    this.componentType = getComponentType(domain);