text:
package fj.data;

import fj.Equal;
import fj.Hash;
import fj.Show;
import fj.F;
import fj.F2;
import fj.Function;
import fj.Monoid;
import fj.Ord;
import fj.P;
import fj.P1;
import fj.P2;
import fj.Unit;
import fj.control.parallel.Promise;
import fj.control.parallel.Strategy;
import fj.Ordering;
import fj.function.Effect1;

import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;

import static fj.Bottom.error;
import static fj.Function.compose;
import static fj.Function.constant;
import static fj.Function.curry;
import static fj.Function.flip;
import static fj.Function.identity;
import static fj.P.p;
import static fj.P.p2;
import static fj.Unit.unit;
import static fj.control.parallel.Promise.promise;
import static fj.data.Array.mkArray;
import static fj.data.Option.none;
import static fj.data.Option.some;
import static fj.function.Booleans.not;
import static fj.Ordering.EQ;
import static fj.Ordering.GT;
import static fj.Ordering.LT;

/**
 * A lazy (not yet evaluated), immutable, singly linked list.
 *
 * @version %build.number%
 */
public abstract class Stream implements Iterable {
  private Stream() {

  }

  /**
   * Returns an iterator for this stream. This method exists to permit the use in a for-each loop.
   *
   * @return A iterator for this stream.
   */
  public final Iterator iterator() {
    return toCollection().iterator();
  }

  /**
   * The first element of the stream or fails for the empty stream.
   *
   * @return The first element of the stream or fails for the empty stream.
   */
  public abstract A head();

  /**
   * The stream without the first element or fails for the empty stream.
   *
   * @return The stream without the first element or fails for the empty stream.
   */
  public abstract P1<Stream> tail();

  /**
   * Returns true if this stream is empty, false otherwise.
   *
   * @return true if this stream is empty, false otherwise.
   */
  public final boolean isEmpty() {
    return this instanceof Nil;
  }

  /**
   * Returns false if this stream is empty, true otherwise.
   *
   * @return false if this stream is empty, true otherwise.
   */
  public final boolean isNotEmpty() {
    return this instanceof Cons;
  }

  /**
   * Performs a reduction on this stream using the given arguments.
   *
   * @param nil  The value to return if this stream is empty.
   * @param cons The function to apply to the head and tail of this stream if it is not empty.
   * @return A reduction on this stream.
   */
  public final  B stream(final B nil, final F<A, F<P1<Stream>, B>> cons) {
    return isEmpty() ? nil : cons.f(head()).f(tail());
  }

  /**
   * Performs a right-fold reduction across this stream. This function uses O(length) stack space.
   *
   * @param f The function to apply on each element of the stream.
   * @param b The beginning value to start the application from.
   * @return The final result after the right-fold reduction.
   */
  public final  B foldRight(final F<A, F<P1, B>> f, final B b) {
    return isEmpty() ? b : f.f(head()).f(new P1() {
      public B _1() {
        return tail()._1().foldRight(f, b);
      }
    });
  }

  /**
   * Performs a right-fold reduction across this stream. This function uses O(length) stack space.
   *
   * @param f The function to apply on each element of the stream.
   * @param b The beginning value to start the application from.
   * @return The final result after the right-fold reduction.
   */
  public final  B foldRight(final F2<A, P1, B> f, final B b) {
    return foldRight(curry(f), b);
  }

  /**
   * Performs a right-fold reduction across this stream. This function uses O(length) stack space.
   *
   * @param f The function to apply on each element of the stream.
   * @param b The beginning value to start the application from.
   * @return The final result after the right-fold reduction.
   */
  public final  B foldRight1(final F<A, F> f, final B b) {
    return foldRight(compose(Function.<P1, B, B>andThen().f(P1.__1()), f), b);
  }

  /**
   * Performs a right-fold reduction across this stream. This function uses O(length) stack space.
   *
   * @param f The function to apply on each element of the stream.
   * @param b The beginning value to start the application from.
   * @return The final result after the right-fold reduction.
   */
  public final  B foldRight1(final F2 f, final B b) {
    return foldRight1(curry(f), b);
  }

  /**
   * Performs a left-fold reduction across this stream. This function runs in constant space.
   *
   * @param f The function to apply on each element of the stream.
   * @param b The beginning value to start the application from.
   * @return The final result after the left-fold reduction.
   */
  public final  B foldLeft(final F<B, F> f, final B b) {
    B x = b;

    for (Stream xs = this; !xs.isEmpty(); xs = xs.tail()._1())
      x = f.f(x).f(xs.head());

    return x;
  }

  /**
   * Performs a left-fold reduction across this stream. This function runs in constant space.
   *
   * @param f The function to apply on each element of the stream.
   * @param b The beginning value to start the application from.
   * @return The final result after the left-fold reduction.
   */
  public final  B foldLeft(final F2 f, final B b) {
    return foldLeft(curry(f), b);
  }

  /**
   * Takes the first 2 elements of the stream and applies the function to them,
   * then applies the function to the result and the third element and so on.
   *
   * @param f The function to apply on each element of the stream.
   * @return The final result after the left-fold reduction.
   */
  public final A foldLeft1(final F2 f) {
    return foldLeft1(curry(f));
  }

  /**
   * Takes the first 2 elements of the stream and applies the function to them,
   * then applies the function to the result and the third element and so on.
   *
   * @param f The function to apply on each element of the stream.
   * @return The final result after the left-fold reduction.
   */
  public final A foldLeft1(final F<A, F> f) {
    if (isEmpty())
      throw error("Undefined: foldLeft1 on empty list");
    return tail()._1().foldLeft(f, head());
  }

  /**
   * Returns the head of this stream if there is one or the given argument if this stream is empty.
   *
   * @param a The argument to return if this stream is empty.
   * @return The head of this stream if there is one or the given argument if this stream is empty.
   */
  public final A orHead(final P1 a) {
    return isEmpty() ? a._1() : head();
  }

  /**
   * Returns the tail of this stream if there is one or the given argument if this stream is empty.
   *
   * @param as The argument to return if this stream is empty.
   * @return The tail of this stream if there is one or the given argument if this stream is empty.
   */
  public final P1<Stream> orTail(final P1<Stream> as) {
    return isEmpty() ? as : tail();
  }

  /**
   * Intersperses the given value between each two elements of the stream.
   *
   * @param a The value to intersperse between values of the stream.
   * @return A new stream with the given value between each two elements of the stream.
   */
  public final Stream intersperse(final A a) {
    return isEmpty() ? this : cons(head(), new P1<Stream>() {
      public Stream _1() {
        return prefix(a, tail()._1());
      }

      public Stream prefix(final A x, final Stream xs) {
        return xs.isEmpty() ? xs : cons(x, p(cons(xs.head(), new P1<Stream>() {
          public Stream _1() {
            return prefix(a, xs.tail()._1());
          }
        })));
      }
    });
  }

  /**
   * Maps the given function across this stream.
   *
   * @param f The function to map across this stream.
   * @return A new stream after the given function has been applied to each element.
   */
  public final  Stream map(final F f) {
    return isEmpty() ? Stream.nil() : cons(f.f(head()), new P1<Stream>() {
      public Stream _1() {
        return tail()._1().map(f);
      }
    });
  }

  /**
   * Provides a first-class version of the map function.
   *
   * @return A function that maps a given function across a given stream.
   */
  public static  F<F, F<Stream, Stream>> map_() {
    return f -> as -> as.map(f);
  }

  /**
   * Performs a side-effect for each element of this stream.
   *
   * @param f The side-effect to perform for the given element.
   * @return The unit value.
   */
  public final Unit foreach(final F f) {
    for (Stream xs = this; xs.isNotEmpty(); xs = xs.tail()._1())
      f.f(xs.head());

    return unit();
  }

  /**
   * Performs a side-effect for each element of this stream.
   *
   * @param f The side-effect to perform for the given element.
   */
  public final void foreachDoEffect(final Effect1 f) {
    for (Stream xs = this; xs.isNotEmpty(); xs = xs.tail()._1())
      f.f(xs.head());
  }

  /**
   * Filters elements from this stream by returning only elements which produce true
   * when the given function is applied to them.
   *
   * @param f The predicate function to filter on.
   * @return A new stream whose elements all match the given predicate.
   */
  public final Stream filter(final F f) {
    final Stream as = dropWhile(not(f));
    return as.isNotEmpty() ? cons(as.head(), new P1<Stream>() {
      public Stream _1() {
        return as.tail()._1().filter(f);
      }
    }) : as;
  }

  /**
   * Appends the given stream to this stream.
   *
   * @param as The stream to append to this one.
   * @return A new stream that has appended the given stream.
   */
  public final Stream append(final Stream as) {
    return isEmpty() ? as : cons(head(), new P1<Stream>() {
      public Stream _1() {
        return tail()._1().append(as);
      }
    });
  }

  /**
   * Appends the given stream to this stream.
   *
   * @param as The stream to append to this one.
   * @return A new stream that has appended the given stream.
   */
  public final Stream append(final P1<Stream> as) {
    return isEmpty() ? as._1() : cons(head(), new P1<Stream>() {
      public Stream _1() {
        return tail()._1().append(as);
      }
    });
  }

  /**
   * Returns a new stream of all the items in this stream that do not appear in the given stream.
   *
   * @param eq an equality for the items of the streams.
   * @param xs a list to subtract from this stream.
   * @return a stream of all the items in this stream that do not appear in the given stream.
   */
  public final Stream minus(final Equal eq, final Stream xs) {
    return removeAll(compose(Monoid.disjunctionMonoid.sumLeftS(), xs.mapM(curry(eq.eq()))));
  }

  /**
   * Filters elements from this stream by returning only elements which produce false when
   * the given function is applied to them.
   *
   * @param f The predicate function to filter on.
   * @return A new stream whose elements do not match the given predicate.
   */
  public final Stream removeAll(final F f) {
    return filter(compose(not, f));
  }

  /**
   * Turn a stream of functions into a function returning a stream.
   *
   * @param fs The stream of functions to sequence into a single function that returns a stream.
   * @return A function that, when given an argument, applies all the functions in the given stream to it
   *         and returns a stream of the results.
   */
  public static  F<B, Stream> sequence_(final Stream<F> fs) {
    return fs.foldRight((baf, p1) -> Function.bind(baf, p1._1(), Function.curry((a, stream) -> cons(a, p(stream)))), Function
        .<B, Stream>constant(Stream.nil()));
  }

  /**
   * Maps the given function of arity-2 across this stream and returns a function that applies all the resulting
   * functions to a given argument.
   *
   * @param f A function of arity-2
   * @return A function that, when given an argument, applies the given function to that argument and every element
   *         in this list.
   */
  public final  F<B, Stream<C>> mapM(final F<A, F> f) {
    return sequence_(map(f));
  }

  /**
   * Binds the given function across each element of this stream with a final join.
   *
   * @param f The function to apply to each element of this stream.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream bind(final F<A, Stream> f) {
    return map(f).foldLeft((accumulator, element) -> {
        Stream result = accumulator;
        for (B single : element) {
            result = result.cons(single);
        }
        return result;
    }, Stream.nil()).reverse();
  }

  /**
   * Binds the given function across each element of this stream and the given stream with a final
   * join.
   *
   * @param sb A given stream to bind the given function with.
   * @param f  The function to apply to each element of this stream and the given stream.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream<C> bind(final Stream sb, final F<A, F> f) {
    return sb.apply(map(f));
  }

  /**
   * Binds the given function across each element of this stream and the given stream with a final
   * join.
   *
   * @param sb A given stream to bind the given function with.
   * @param f  The function to apply to each element of this stream and the given stream.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream<C> bind(final Stream sb, final F2 f) {
    return bind(sb, curry(f));
  }

  /**
   * Binds the given function across each element of this stream and the given streams with a final
   * join.
   *
   * @param sb A given stream to bind the given function with.
   * @param sc A given stream to bind the given function with.
   * @param f  The function to apply to each element of this stream and the given streams.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream<D> bind(final Stream sb, final Stream<C> sc, final F<A, F<B, F<C, D>>> f) {
    return sc.apply(bind(sb, f));
  }

  /**
   * Binds the given function across each element of this stream and the given streams with a final
   * join.
   *
   * @param sb A given stream to bind the given function with.
   * @param sc A given stream to bind the given function with.
   * @param sd A given stream to bind the given function with.
   * @param f  The function to apply to each element of this stream and the given streams.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream<E> bind(final Stream sb, final Stream<C> sc, final Stream<D> sd,
                                     final F<A, F<B, F<C, F<D, E>>>> f) {
    return sd.apply(bind(sb, sc, f));
  }

  /**
   * Binds the given function across each element of this stream and the given streams with a final
   * join.
   *
   * @param sb A given stream to bind the given function with.
   * @param sc A given stream to bind the given function with.
   * @param sd A given stream to bind the given function with.
   * @param se A given stream to bind the given function with.
   * @param f  The function to apply to each element of this stream and the given streams.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream<F$> bind(final Stream sb, final Stream<C> sc, final Stream<D> sd,
                                          final Stream<E> se, final F<A, F<B, F<C, F<D, F<E, F$>>>>> f) {
    return se.apply(bind(sb, sc, sd, f));
  }

  /**
   * Binds the given function across each element of this stream and the given streams with a final
   * join.
   *
   * @param sb A given stream to bind the given function with.
   * @param sc A given stream to bind the given function with.
   * @param sd A given stream to bind the given function with.
   * @param se A given stream to bind the given function with.
   * @param sf A given stream to bind the given function with.
   * @param f  The function to apply to each element of this stream and the given streams.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream<G> bind(final Stream sb, final Stream<C> sc, final Stream<D> sd,
                                            final Stream<E> se, final Stream<F$> sf,
                                            final F<A, F<B, F<C, F<D, F<E, F<F$, G>>>>>> f) {
    return sf.apply(bind(sb, sc, sd, se, f));
  }

  /**
   * Binds the given function across each element of this stream and the given streams with a final
   * join.
   *
   * @param sb A given stream to bind the given function with.
   * @param sc A given stream to bind the given function with.
   * @param sd A given stream to bind the given function with.
   * @param se A given stream to bind the given function with.
   * @param sf A given stream to bind the given function with.
   * @param sg A given stream to bind the given function with.
   * @param f  The function to apply to each element of this stream and the given streams.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream<H> bind(final Stream sb, final Stream<C> sc, final Stream<D> sd,
                                               final Stream<E> se, final Stream<F$> sf, final Stream<G> sg,
                                               final F<A, F<B, F<C, F<D, F<E, F<F$, F<G, H>>>>>>> f) {
    return sg.apply(bind(sb, sc, sd, se, sf, f));
  }

  /**
   * Binds the given function across each element of this stream and the given streams with a final
   * join.
   *
   * @param sb A given stream to bind the given function with.
   * @param sc A given stream to bind the given function with.
   * @param sd A given stream to bind the given function with.
   * @param se A given stream to bind the given function with.
   * @param sf A given stream to bind the given function with.
   * @param sg A given stream to bind the given function with.
   * @param sh A given stream to bind the given function with.
   * @param f  The function to apply to each element of this stream and the given streams.
   * @return A new stream after performing the map, then final join.
   */
  public final  Stream bind(final Stream sb, final Stream<C> sc, final Stream<D> sd,
                                                  final Stream<E> se, final Stream<F$> sf, final Stream<G> sg,
                                                  final Stream<H> sh,
                                                  final F<A, F<B, F<C, F<D, F<E, F<F$, F<G, F<H, I>>>>>>>> f) {
    return sh.apply(bind(sb, sc, sd, se, sf, sg, f));
  }

  /**
   * Performs a bind across each stream element, but ignores the element value each time.
   *
   * @param bs The stream to apply in the final join.
   * @return A new stream after the final join.
   */
  public final  Stream sequence(final Stream bs) {
    final F<A, Stream> c = constant(bs);
    return bind(c);
  }

  /**
   * Performs function application within a stream (applicative functor pattern).
   *
   * @param sf The stream of functions to apply.
   * @return A new stream after applying the given stream of functions through this stream.
   */
  public final  Stream apply(final Stream<F> sf) {
    return sf.bind(f -> map(a -> f.f(a)));
  }

  /**
   * Interleaves the given stream with this stream to produce a new stream.
   *
   * @param as The stream to interleave this stream with.
   * @return A new stream with elements interleaved from this stream and the given stream.
   */
  public final Stream interleave(final Stream as) {
    return isEmpty() ? as : as.isEmpty() ? this : cons(head(), new P1<Stream>() {
      @Override public Stream _1() {
        return as.interleave(tail()._1());
      }
    });
  }

  /**
   * Sort this stream according to the given ordering.
   *
   * @param o An ordering for the elements of this stream.
   * @return A new stream with the elements of this stream sorted according to the given ordering.
   */
  public final Stream sort(final Ord o) {
    return mergesort(o, map(flip(Stream.cons()).f(p(Stream.nil()))));
  }

  // Merges a stream of individually sorted streams into a single sorted stream.
  private static  Stream mergesort(final Ord o, final Stream<Stream> s) {
    if (s.isEmpty())
      return nil();
    Stream<Stream> xss = s;
    while (xss.tail()._1().isNotEmpty())
      xss = mergePairs(o, xss);
    return xss.head();
  }

  // Merges individually sorted streams two at a time.
  private static  Stream<Stream> mergePairs(final Ord o, final Stream<Stream> s) {
    if (s.isEmpty() || s.tail()._1().isEmpty())
      return s;
    final Stream<Stream> t = s.tail()._1();
    return cons(merge(o, s.head(), t.head()), new P1<Stream<Stream>>() {
      public Stream<Stream> _1() {
        return mergePairs(o, t.tail()._1());
      }
    });
  }

  // Merges two individually sorted streams.
  private static  Stream merge(final Ord o, final Stream xs, final Stream ys) {
    if (xs.isEmpty())
      return ys;
    if (ys.isEmpty())
      return xs;
    final A x = xs.head();
    final A y = ys.head();
    if (o.isGreaterThan(x, y))
      return cons(y, new P1<Stream>() {
        public Stream _1() {
          return merge(o, xs, ys.tail()._1());
        }
      });
    return cons(x, new P1<Stream>() {
      public Stream _1() {
        return merge(o, xs.tail()._1(), ys);
      }
    });
  }

  /**
   * Sort this stream according to the given ordering, using a parallel Quick Sort algorithm that uses the given
   * parallelisation strategy.
   *
   * @param o An ordering for the elements of this stream.
   * @param s A strategy for parallelising the algorithm.
   * @return A new stream with the elements of this stream sorted according to the given ordering.
   */
  public final Stream sort(final Ord o, final Strategy<Unit> s) {
    return qs(o, s).claim();
  }

  private Promise<Stream> qs(final Ord o, final Strategy<Unit> s) {
    if (isEmpty())
      return promise(s, P.p(this));
    else {
      final F<Boolean, Boolean> id = identity();
      final A x = head();
      final P1<Stream> xs = tail();
      final Promise<Stream> left = Promise.join(s, xs.map(flt(o, s, x, id)));
      final Promise<Stream> right = xs.map(flt(o, s, x, not))._1();
      final Monoid<Stream> m = Monoid.streamMonoid();
      return right.fmap(m.sum(single(x))).apply(left.fmap(m.sum()));
    }
  }

  private static  F<Stream, Promise<Stream>> qs_(final Ord o, final Strategy<Unit> s) {
    return xs -> xs.qs(o, s);
  }

  private static  F<Stream, Promise<Stream>> flt(final Ord o,
                                                          final Strategy<Unit> s,
                                                          final A x,
                                                          final F<Boolean, Boolean> f) {
    final F<F, F<Stream, Stream>> filter = filter();
    final F lt = o.isLessThan(x);
    return compose(qs_(o, s), filter.f(compose(f, lt)));
  }

  /**
   * Projects an immutable collection of this stream.
   *
   * @return An immutable collection of this stream.
   */
  public final Collection toCollection() {
    return new AbstractCollection() {
      public Iterator iterator() {
        return new Iterator() {
          private Stream xs = Stream.this;

          public boolean hasNext() {
            return xs.isNotEmpty();
          }

          public A next() {
            if (xs.isEmpty())
              throw new NoSuchElementException();
            else {
              final A a = xs.head();
              xs = xs.tail()._1();
              return a;
            }
          }

          public void remove() {
            throw new UnsupportedOperationException();
          }
        };
      }

      public int size() {
        return length();
      }
    };
  }

  /**
   * Returns a stream of integers from the given from value (inclusive) to the given
   * to value (exclusive).
   *
   * @param from The minimum value for the stream (inclusive).
   * @param to   The maximum value for the stream (exclusive).
   * @return A stream of integers from the given from value (inclusive) to the given
   *         to value (exclusive).
   */
  public static Stream<Integer> range(final int from, final long to) {
    return from >= to ? Stream.<Integer>nil() : cons(from, new P1<Stream<Integer>>() {
      public Stream<Integer> _1() {
        return range(from + 1, to);
      }
    });
  }

  /**
   * Constructs a stream with the given elements.
   *
   * @param as The elements which which to construct a stream.
   * @return a new stream with the given elements.
   */
  public static  Stream stream(final A... as) {
    return as.length == 0 ? Stream.nil()
                          : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.<P2<A, P2>>none()
                                                : some(P.p(as[i], P.p(as, i + 1)))), P.p(as, 0));
  }

  public static  Stream stream(Iterable it) {
    return iterableStream(it);
  }

  public static  Stream stream(Iterator it) {
    return iteratorStream(it);
  }

  /**
   * Returns a stream that is either infinite or bounded up to the maximum value of the given iterator starting at the
   * given value and stepping at increments of 1.
   *
   * @param e    The enumerator to compute successors from.
   * @param from The value to begin computing successors from.
   * @return A stream that is either infinite or bounded up to the maximum value of the given iterator starting at the
   *         given value and stepping at increments of 1.
   */
  public static  Stream forever(final Enumerator e, final A from) {
    return forever(e, from, 1L);
  }

  /**
   * Returns a stream that is either infinite or bounded up to the maximum value of the given iterator starting at the
   * given value and stepping at the given increment.
   *
   * @param e    The enumerator to compute successors from.
   * @param from The value to begin computing successors from.
   * @param step The increment to step.
   * @return A stream that is either infinite or bounded up to the maximum value of the given iterator starting at the
   *         given value and stepping at the given increment.
   */
  public static  Stream forever(final Enumerator e, final A from, final long step) {
    return cons(from, new P1<Stream>() {
      public Stream _1() {
        return e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil());
      }
    });
  }

  /**
   * Returns a stream using the given enumerator from the given value to the other given value stepping at increments of
   * 1.
   *
   * @param e    The enumerator to compute successors from.
   * @param from The value to begin computing successors from.
   * @param to   The value to stop computing successors from.
   * @return A stream using the given enumerator from the given value to the other given value stepping at increments of
   *         1.
   */
  public static  Stream range(final Enumerator e, final A from, final A to) {
    return range(e, from, to, 1L);
  }

  /**
   * Returns a stream using the given enumerator from the given value to the other given value stepping at the given
   * increment.
   *
   * @param e    The enumerator to compute successors from.
   * @param from The value to begin computing successors from.
   * @param to   The value to stop computing successors from.
   * @param step The increment to step.
   * @return A stream using the given enumerator from the given value to the other given value stepping at the given
   *         increment.
   */
  public static  Stream range(final Enumerator e, final A from, final A to, final long step) {
    final Ordering o = e.order().compare(from, to);
    return o == EQ || step > 0L && o == GT || step < 0L && o == LT ? single(from) : cons(from, new P1<Stream>() {
      public Stream _1() {
        return Stream.join(e.plus(from, step).filter(a -> !(o == LT
                ? e.order().isLessThan(to, a)
                : e.order().isGreaterThan(to, a))).map(a1 -> range(e, a1, to, step)).toStream());
      }
    });
  }

  /**
   * Returns an infinite stream of integers from the given from value (inclusive).
   *
   * @param from The minimum value for the stream (inclusive).
   * @return A stream of integers from the given from value (inclusive).
   */
  public static Stream<Integer> range(final int from) {
    return cons(from, new P1<Stream<Integer>>() {
      public Stream<Integer> _1() {
        return range(from + 1);
      }
    });
  }

  /**
   * Returns a first-class version of the filter function.
   *
   * @return a function that filters a given stream using a given predicate.
   */
  public static  F<F, F<Stream, Stream>> filter() {
    return curry((f, as) -> as.filter(f));
  }

  /**
   * Zips this stream with the given stream of functions, applying each function in turn to the
   * corresponding element in this stream to produce a new stream. If this stream and the given stream
   * have different lengths, then the longer stream is normalised so this function never fails.
   *
   * @param fs The stream of functions to apply to this stream.
   * @return A new stream with a length the same as the shortest of this stream and the given stream.
   */
  public final  Stream zapp(final Stream<F> fs) {
    return fs.isEmpty() || isEmpty() ? Stream.nil() :
           cons(fs.head().f(head()), new P1<Stream>() {
             public Stream _1() {
               return tail()._1().zapp(fs.tail()._1());
             }
           });
  }

  /**
   * Zips this stream with the given stream using the given function to produce a new stream. If
   * this stream and the given stream have different lengths, then the longer stream is normalised
   * so this function never fails.
   *
   * @param bs The stream to zip this stream with.
   * @param f  The function to zip this stream and the given stream with.
   * @return A new stream with a length the same as the shortest of this stream and the given
   *         stream.
   */
  public final  Stream<C> zipWith(final Stream bs, final F<A, F> f) {
    return bs.zapp(zapp(repeat(f)));
  }

  /**
   * Zips this stream with the given stream using the given function to produce a new stream. If
   * this stream and the given stream have different lengths, then the longer stream is normalised
   * so this function never fails.
   *
   * @param bs The stream to zip this stream with.
   * @param f  The function to zip this stream and the given stream with.
   * @return A new stream with a length the same as the shortest of this stream and the given
   *         stream.
   */
  public final  Stream<C> zipWith(final Stream bs, final F2 f) {
    return zipWith(bs, curry(f));
  }

  /**
   * Partially-applied version of zipWith.
   * Returns a function that zips a given stream with this stream using the given function.
   *
   * @param f The function to zip this stream and a given stream with.
   * @return A function that zips a given stream with this stream using the given function.
   */
  public final  F<Stream, Stream<C>> zipWith(final F<A, F> f) {
    return stream -> zipWith(stream, f);
  }

  /**
   * Zips this stream with the given stream to produce a stream of pairs. If this stream and the
   * given stream have different lengths, then the longer stream is normalised so this function
   * never fails.
   *
   * @param bs The stream to zip this stream with.
   * @return A new stream with a length the same as the shortest of this stream and the given
   *         stream.
   */
  public final  Stream<P2> zip(final Stream bs) {
    final F<A, F<B, P2>> __2 = p2();
    return zipWith(bs, __2);
  }

  /**
   * Zips this stream with the index of its element as a pair.
   *
   * @return A new stream with the same length as this stream.
   */
  public final Stream<P2> zipIndex() {
    return zipWith(range(0), (a, i) -> p(a, i));
  }

  /**
   * Returns an either projection of this stream; the given argument in Left if empty,
   * or the first element in Right.
   *
   * @param x The value to return in left if this stream is empty.
   * @return An either projection of this stream.
   */
  public final <X> Either<X, A> toEither(final P1<X> x) {
    return isEmpty() ? Either.<X, A>left(x._1()) : Either.<X, A>right(head());
  }

  /**
   * Returns an option projection of this stream; None if empty, or the first element
   * in Some.
   *
   * @return An option projection of this stream.
   */
  public final Option toOption() {
    return isEmpty() ? Option.none() : some(head());
  }

  /**
   * Returns a list projection of this stream.
   *
   * @return A list projection of this stream.
   */
  public final List toList() {
    List as = List.nil();

    for (Stream x = this; !x.isEmpty(); x = x.tail()._1()) {
      as = as.snoc(x.head());
    }

    return as;
  }

  /**
   * Returns a array projection of this stream.
   *
   * @return A array projection of this stream.
   */
  @SuppressWarnings({"unchecked"})
  public final Array toArray() {
    final int l = length();
    final Object[] a = new Object[l];
    Stream x = this;
    for (int i = 0; i < l; i++) {
      a[i] = x.head();
      x = x.tail()._1();
    }

    return mkArray(a);
  }

  /**
   * Returns a array projection of this stream.
   *
   * @param c The class type of the array to return.
   * @return A array projection of this stream.
   */
  @SuppressWarnings({"unchecked", "UnnecessaryFullyQualifiedName"})
  public final Array toArray(final Class c) {
    final A[] a = (A[]) java.lang.reflect.Array.newInstance(c.getComponentType(), length());

    int i = 0;
    for (final A x : this) {
      a[i] = x;
      i++;
    }

    return Array.array(a);
  }

  /**
   * Returns an array from this stream.
   *
   * @param c The class type of the array to return.
   * @return An array from this stream.
   */
  public final A[] array(final Class c) {
    return toArray(c).array(c);
  }

  /**
   * Prepends (cons) the given element to this stream to product a new stream.
   *
   * @param a The element to prepend.
   * @return A new stream with the given element at the head.
   */
  public final Stream cons(final A a) {
    return new Cons(a, new P1<Stream>() {
      public Stream _1() {
        return Stream.this;
      }
    });
  }

  /**
   * Returns a string from the given stream of characters. The inverse of this function is {@link
   * #fromString(String)}.
   *
   * @param cs The stream of characters to produce the string from.
   * @return A string from the given stream of characters.
   */
  public static String asString(final Stream<Character> cs) {
    return LazyString.fromStream(cs).toString();
  }

  /**
   * Returns a stream of characters from the given string. The inverse of this function is {@link
   * #asString(Stream)}.
   *
   * @param s The string to produce the stream of characters from.
   * @return A stream of characters from the given string.
   */
  public static Stream<Character> fromString(final String s) {
    return LazyString.str(s).toStream();
  }

  /**
   * Append the given element to this stream to product a new stream.
   *
   * @param a The element to append.
   * @return A new stream with the given element at the end.
   */
  public final Stream snoc(final A a) {
    return snoc(p(a));
  }

  /**
   * Append the given element to this stream to produce a new stream.
   *
   * @param a The element to append.
   * @return A new stream with the given element at the end.
   */
  public final Stream snoc(final P1 a) {
    return append(new P1<Stream>() {
      public Stream _1() {
        return single(a._1());
      }
    });
  }

  /**
   * Returns the first n elements from the head of this stream.
   *
   * @param n The number of elements to take from this stream.
   * @return The first n elements from the head of this stream.
   */
  public final Stream take(final int n) {
    return n <= 0 || isEmpty() ?
           Stream.nil() :
           cons(head(), new P1<Stream>() {
             public Stream _1() {
               return tail()._1().take(n - 1);
             }
           });
  }

  /**
   * Drops the given number of elements from the head of this stream if they are available.
   *
   * @param i The number of elements to drop from the head of this stream.
   * @return A stream with a length the same, or less than, this stream.
   */
  public final Stream drop(final int i) {
    int c = 0;

    Stream xs = this;

    for (; xs.isNotEmpty() && c < i; xs = xs.tail()._1())
      c++;

    return xs;
  }

  /**
   * Returns the first elements of the head of this stream that match the given predicate function.
   *
   * @param f The predicate function to apply on this stream until it finds an element that does not
   *          hold, or the stream is exhausted.
   * @return The first elements of the head of this stream that match the given predicate function.
   */
  public final Stream takeWhile(final F f) {
    return isEmpty() ?
           this :
           f.f(head()) ?
           cons(head(), new P1<Stream>() {
             public Stream _1() {
               return tail()._1().takeWhile(f);
             }
           }) :
           Stream.nil();
  }

  /**
   * Removes elements from the head of this stream that do not match the given predicate function
   * until an element is found that does match or the stream is exhausted.
   *
   * @param f The predicate function to apply through this stream.
   * @return The stream whose first element does not match the given predicate function.
   */
  public final Stream dropWhile(final F f) {
    Stream as;
    //noinspection StatementWithEmptyBody
    for (as = this; !as.isEmpty() && f.f(as.head()); as = as.tail()._1()) ;

    return as;
  }

  /**
   * Returns a tuple where the first element is the longest prefix of this stream that satisfies
   * the given predicate and the second element is the remainder of the stream.
   *
   * @param p A predicate to be satisfied by a prefix of this stream.
   * @return A tuple where the first element is the longest prefix of this stream that satisfies
   *         the given predicate and the second element is the remainder of the stream.
   */
  public final P2<Stream, Stream> span(final F p) {
    if (isEmpty())
      return p(this, this);
    else if (p.f(head())) {
      final P1<P2<Stream, Stream>> yszs = new P1<P2<Stream, Stream>>() {
        @Override public P2<Stream, Stream> _1() {
          return tail()._1().span(p);
        }
      };
      return new P2<Stream, Stream>() {
        @Override public Stream _1() {
          return cons(head(), yszs.map(P2.<Stream, Stream>__1()));
        }

        @Override public Stream _2() {
          return yszs._1()._2();
        }
      };
    } else
      return p(Stream.nil(), this);
  }

  /**
   * Returns a new stream resulting from replacing all elements that match the given predicate with the given element.
   *
   * @param p The predicate to match replaced elements.
   * @param a The element with which to replace elements.
   * @return A new stream resulting from replacing all elements that match the given predicate with the given element.
   */
  public final Stream replace(final F p, final A a) {
    if (isEmpty())
      return nil();
    else {
      final P2<Stream, Stream> s = span(p);
      return s._1().append(cons(a, new P1<Stream>() {
        @Override public Stream _1() {
          return s._2().tail()._1().replace(p, a);
        }
      }));
    }
  }

  /**
   * Returns a tuple where the first element is the longest prefix of this stream that does not satisfy
   * the given predicate and the second element is the remainder of the stream.
   *
   * @param p A predicate not to be satisfied by a prefix of this stream.
   * @return A tuple where the first element is the longest prefix of this stream that does not satisfy
   *         the given predicate and the second element is the remainder of the stream.
   */
  public final P2<Stream, Stream> split(final F p) {
    return span(compose(not, p));
  }

  /**
   * Reverse this stream in constant stack space.
   *
   * @return A new stream that is the reverse of this one.
   */
  public final Stream reverse() {
    return foldLeft(as -> {
        return a -> cons(a, new P1<Stream>() {
            public Stream _1() {
                return as;
            }
        });
    }, Stream.nil());
  }

  /**
   * Get the last element of this stream. Undefined for infinite streams.
   *
   * @return The last element in this stream, if there is one.
   */
  public final A last() {
    return reverse().head();
  }

  /**
   * The length of this stream. This function will not terminate for an infinite stream.
   *
   * @return The length of this stream.
   */
  public final int length() {
    // we're using an iterative approach here as the previous implementation (toList().length()) took
    // very long even for some 10000 elements.
    Stream xs = this;
    int i = 0;
    while (!xs.isEmpty()) {
      xs = xs.tail()._1();
      i += 1;
    }
    return i;
  }

  /**
   * Returns the element at the given index if it exists, fails otherwise.
   *
   * @param i The index at which to get the element to return.
   * @return The element at the given index if it exists, fails otherwise.
   */
  public final A index(final int i) {
    if (i < 0)
      throw error("index " + i + " out of range on stream");
    else {
      Stream xs = this;

      for (int c = 0; c < i; c++) {
        if (xs.isEmpty())
          throw error("index " + i + " out of range on stream");

        xs = xs.tail()._1();
      }

      if (xs.isEmpty())
        throw error("index " + i + " out of range on stream");

      return xs.head();
    }
  }

  /**
   * Returns true if the predicate holds for all of the elements of this stream,
   * false otherwise (true for the empty stream).
   *
   * @param f the predicate function to test on each element of this stream.
   * @return true if the predicate holds for all of the elements of this stream,
   *         false otherwise.
   */
  public final boolean forall(final F f) {
    return isEmpty() || f.f(head()) && tail()._1().forall(f);
  }

  @Override
  public boolean equals(Object other) {
    return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.streamEqual(Equal.anyEqual()).eq(this, (Stream) other)));
  }

  @Override
  public int hashCode() {
    return Hash.streamHash(Hash.anyHash()).hash(this);
  }

  @Override
  public String toString() {
    return Show.streamShow(Show.anyShow()).showS(this);
  }

  /**
   * Returns true if the predicate holds for at least one of the elements of this
   * stream, false otherwise (false for the empty stream).
   *
   * @param f The predicate function to test on the elements of this stream.
   * @return true if the predicate holds for at least one of the elements of this
   *         stream.
   */
  public final boolean exists(final F f) {
    return dropWhile(not(f)).isNotEmpty();
  }

  /**
   * Finds the first occurrence of an element that matches the given predicate or no value if no
   * elements match.
   *
   * @param f The predicate function to test on elements of this stream.
   * @return The first occurrence of an element that matches the given predicate or no value if no
   *         elements match.
   */
  public final Option find(final F f) {
    for (Stream as = this; as.isNotEmpty(); as = as.tail()._1()) {
      if (f.f(as.head()))
        return some(as.head());
    }

    return none();
  }

  /**
   * Binds the given function across the stream of substreams of this stream.
   *
   * @param k A function to bind across this stream and its substreams.
   * @return a new stream of the results of applying the given function to this stream and its substreams.
   */
  public final  Stream cobind(final F<Stream, B> k) {
    return substreams().map(k);
  }

  /**
   * Returns a stream of the suffixes of this stream. A stream is considered to be a suffix of itself in this context.
   *
   * @return a stream of the suffixes of this stream, starting with the stream itself.
   */
  public final Stream<Stream> tails() {
    return isEmpty() ? Stream.<Stream>nil() : cons(this, new P1<Stream<Stream>>() {
      public Stream<Stream> _1() {
        return tail()._1().tails();
      }
    });
  }

  /**
   * Returns a stream of all prefixes of this stream. A stream is considered a prefix of itself in tnis context.
   *
   * @return a stream of the prefixes of this stream, starting with the stream itself.
   */
  public final Stream<Stream> inits() {
    final Stream<Stream> nil = Stream.cons(Stream.nil(), new P1<Stream<Stream>>() {
      public Stream<Stream> _1() {
        return nil();
      }
    });
    return isEmpty() ? nil : nil.append(new P1<Stream<Stream>>() {
      public Stream<Stream> _1() {
        return tail()._1().inits().map(Stream.cons_().f(head()));
      }
    });
  }

  /**
   * Returns a stream of all infixes of this stream. A stream is considered to contain itself.
   *
   * @return a stream of the infixes of this stream.
   */
  public final Stream<Stream> substreams() {
    return tails().bind(stream -> stream.inits());
  }

  /**
   * Returns the position of the first element matching the given predicate, if any.
   *
   * @param p A predicate to match.
   * @return the position of the first element matching the given predicate, if any.
   */
  public final Option<Integer> indexOf(final F p) {
    return zipIndex().find(p2 -> p.f(p2._1())).map(P2.__2());
  }

  /**
   * Applies a stream of comonadic functions to this stream, returning a stream of values.
   *
   * @param fs A stream of comonadic functions to apply to this stream.
   * @return A new stream of the results of applying the stream of functions to this stream.
   */
  public final  Stream sequenceW(final Stream<F<Stream, B>> fs) {
    return fs.isEmpty()
           ? Stream.nil()
           : cons(fs.head().f(this), new P1<Stream>() {
             public Stream _1() {
               return sequenceW(fs.tail()._1());
             }
           });
  }

  /**
   * Converts this stream to a function of natural numbers.
   *
   * @return A function from natural numbers to values with the corresponding position in this stream.
   */
  public final F<Integer, A> toFunction() {
    return i -> index(i);
  }

  /**
   * Converts a function of natural numbers to a stream.
   *
   * @param f The function to convert to a stream.
   * @return A new stream of the results of the given function applied to the natural numbers, starting at 0.
   */
  public static  Stream fromFunction(final F<Natural, A> f) {
    return fromFunction(Enumerator.naturalEnumerator, f, Natural.ZERO);
  }

  /**
   * Converts a function of an enumerable type to a stream of the results of that function,
   * starting at the given index.
   *
   * @param e An enumerator for the domain of the function.
   * @param f The function to convert to a stream.
   * @param i The index into the function at which to begin the stream.
   * @return A new stream of the results of the given function applied to the values of the given enumerator,
   *         starting at the given value.
   */
  public static  Stream fromFunction(final Enumerator e, final F f, final B i) {
    return cons(f.f(i), new P1<Stream>() {
      public Stream _1() {
        final Option s = e.successor(i);
        return s.isSome()
               ? fromFunction(e, f, s.some())
               : Stream.nil();
      }
    });
  }

  /**
   * Transforms a stream of pairs into a stream of first components and a stream of second components.
   *
   * @param xs The stream of pairs to transform.
   * @return A stream of first components and a stream of second components.
   */
  public static  P2<Stream, Stream> unzip(final Stream<P2> xs) {
    return xs.foldRight((p, ps) -> {
      final P2<Stream, Stream> pp = ps._1();
      return P.p(cons(p._1(), P.p(pp._1())), cons(p._2(), P.p(pp._2())));
    }, P.p(Stream.nil(), Stream.nil()));
  }

  /**
   * A first-class version of the zipWith function.
   *
   * @return a function that zips two given streams with a given function.
   */
  public static  F<Stream, F<Stream, F<F<A, F>, Stream<C>>>> zipWith() {
    return curry((as, bs, f) -> as.zipWith(bs, f));
  }

  private static final class Nil extends Stream {
    public A head() {
      throw error("head on empty stream");
    }

    public P1<Stream> tail() {
      throw error("tail on empty stream");
    }
  }

  private static final class Cons extends Stream {
    private final A head;
    private final P1<Stream> tail;

    Cons(final A head, final P1<Stream> tail) {
      this.head = head;
      this.tail = tail.memo();
    }

    public A head() {
      return head;
    }

    public P1<Stream> tail() {
      return tail;
    }

  }

  /**
   * Returns a function that prepends (cons) an element to a stream to produce a new stream.
   *
   * @return A function that prepends (cons) an element to a stream to produce a new stream.
   */
  public static  F<A, F<P1<Stream>, Stream>> cons() {
    return a -> list -> cons(a, list);
  }

  /**
   * Returns a function that prepends (cons) an element to a stream to produce a new stream.
   *
   * @return A function that prepends (cons) an element to a stream to produce a new stream.
   */
  public static  F<A, F<Stream, Stream>> cons_() {
    return curry((a, as) -> as.cons(a));
  }

  /**
   * Returns an empty stream.
   *
   * @return An empty stream.
   */
  public static  Stream nil() {
    return new Nil();
  }

  /**
   * Returns an empty stream.
   *
   * @return An empty stream.
   */
  public static  P1<Stream> nil_() {
    return new P1<Stream>() {
      public Stream _1() {
        return new Nil();
      }
    };
  }

  /**
   * Returns a function that determines whether a given stream is empty.
   *
   * @return A function that determines whether a given stream is empty.
   */
  public static  F<Stream, Boolean> isEmpty_() {
    return as -> as.isEmpty();
  }

  /**
   * Returns a function that determines whether a given stream is not empty.
   *
   * @return A function that determines whether a given stream is not empty.
   */
  public static  F<Stream, Boolean> isNotEmpty_() {
    return as -> as.isNotEmpty();
  }

  /**
   * Returns a stream of one element containing the given value.
   *
   * @param a The value for the head of the returned stream.
   * @return A stream of one element containing the given value.
   */
  public static  Stream single(final A a) {
    return cons(a, new P1<Stream>() {
      public Stream _1() {
        return nil();
      }
    });
  }

  /**
   * Returns a function that yields a stream containing its argument.
   *
   * @return a function that yields a stream containing its argument.
   */
  public static  F<A, Stream> single() {
    return a -> single(a);
  }

  /**
   * Prepends the given head element to the given tail element to produce a new stream.
   *
   * @param head The element to prepend.
   * @param tail The stream to prepend to.
   * @return The stream with the given element prepended.
   */
  public static  Stream cons(final A head, final P1<Stream> tail) {
    return new Cons(head, tail);
  }

  /**
   * Joins the given stream of streams by concatenation.
   *
   * @param o The stream of streams to join.
   * @return A new stream that is the join of the given streams.
   */
  public static  Stream join(final Stream<Stream> o) {
    return Monoid.streamMonoid().sumRight(o);
  }

  /**
   * A first-class version of join
   *
   * @return A function that joins a stream of streams using a bind operation.
   */
  public static  F<Stream<Stream>, Stream> join() {
    return as -> join(as);
  }

  /**
   * Unfolds across the given function starting at the given value to produce a stream.
   *
   * @param f The function to unfold across.
   * @param b The start value to begin the unfold.
   * @return A new stream that is a result of unfolding until the function does not produce a
   *         value.
   */
  public static  Stream unfold(final F<B, Option<P2>> f, final B b) {
    final Option<P2> o = f.f(b);
    if (o.isNone())
      return nil();
    else {
      final P2 p = o.some();
      return cons(p._1(), new P1<Stream>() {
        public Stream _1() {
          return unfold(f, p._2());
        }
      });
    }
  }

  /**
   * Creates a stream where the first item is calculated by applying the function on the third argument,
   * the second item by applying the function on the previous result and so on.
   *
   * @param f The function to iterate with.
   * @param p The predicate which must be true for the next item in order to continue the iteration.
   * @param a The input to the first iteration.
   * @return A stream where the first item is calculated by applying the function on the third argument,
   *         the second item by applying the function on the previous result and so on.
   */
  public static  Stream iterateWhile(final F f, final F p, final A a) {
    return unfold(
            o -> Option.iif(p2 -> p.f(o), P.p(o, f.f(o)))
            , a);
  }

  /**
   * Takes the given iterable to a stream.
   *
   * @param i The iterable to take to a stream.
   * @return A stream from the given iterable.
   */
  public static  Stream iterableStream(final Iterable i) {
    return iteratorStream(i.iterator());
  }

  /**
   * Takes the given iterator to a stream.
   *
   * @param i The iterator to take to a stream.
   * @return A stream from the given iterator.
   */
  public static  Stream iteratorStream(final Iterator i) {
    if (i.hasNext()) {
      final A a = i.next();
      return cons(a, P.lazy(u -> iteratorStream(i)));
    } else
      return nil();
  }

  /**
   * Returns an infinite-length stream of the given element.
   *
   * @param a The element to repeat infinitely.
   * @return An infinite-length stream of the given element.
   */
  public static  Stream repeat(final A a) {
    return cons(a, new P1<Stream>() {
      public Stream _1() {
        return repeat(a);
      }
    });
  }

  /**
   * Returns an infinite-length stream of the given elements cycling. Fails on the empty stream.
   *
   * @param as The elements to cycle infinitely. This must not be empty.
   * @return An infinite-length stream of the given elements cycling.
   */
  public static  Stream cycle(final Stream as) {
    if (as.isEmpty())
      throw error("cycle on empty list");
    else
      return as.append(new P1<Stream>() {
        public Stream _1() {
          return cycle(as);
        }
      });
  }

  /**
   * Returns a stream constructed by applying the given iteration function starting at the given value.
   *
   * @param f The iteration function.
   * @param a The value to begin iterating from.
   * @return A stream constructed by applying the given iteration function starting at the given value.
   */
  public static  Stream iterate(final F f, final A a) {
    return cons(a, new P1<Stream>() {
      public Stream _1() {
        return iterate(f, f.f(a));
      }
    });
  }

  /**
   * A first-class version of the iterate function.
   *
   * @return A function that returns a stream constructed by applying a given iteration function
   *         starting at a given value.
   */
  public static  F<F, F<A, Stream>> iterate() {
    return curry((f, a) -> iterate(f, a));
  }

  /**
   * A first-class version of the bind function.
   *
   * @return A function that binds a given function across a given stream, joining the resulting streams.
   */
  public static  F<F<A, Stream>, F<Stream, Stream>> bind_() {
    return curry((f, as) -> as.bind(f));
  }

  /**
   * A first-class version of the foldRight function.
   *
   * @return A function that folds a given stream with a given function.
   */
  public static  F<F<A, F<P1, B>>, F<B, F<Stream, B>>> foldRight() {
    return curry((f, b, as) -> as.foldRight(f, b));
  }
}


text:
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * Stub out the metrics package.
 * @type {!Object<!string, !Function>}
 */
var metrics = {
  recordTime: function() {},
  recordValue: function() {}
};

/** @type {!importer.DefaultMediaScanner} */
var scanner;

/** @type {!importer.TestImportHistory} */
var importHistory;

/** @type {!importer.TestDirectoryWatcher} */
var watcher;

/**
 * @type {function(!FileEntry, !importer.Destination):
 *     !Promise<!importer.Disposition>}
 */
var dispositionChecker;

// Set up the test components.
function setUp() {

  importHistory = new importer.TestImportHistory();
  // This is the default disposition checker.
  // Tests can replace this at runtime if they
  // want specialized behaviors.
  dispositionChecker = function() {
    return Promise.resolve(importer.Disposition.ORIGINAL);
  };

  scanner = new importer.DefaultMediaScanner(
      /** @param {!FileEntry} entry */
      function(entry) {
        return Promise.resolve(entry.name);
      },
      function(entry, destination) {
        return dispositionChecker(entry, destination);
      },
      function(callback) {
        watcher = new TestDirectoryWatcher(callback);
        return watcher;
      });
}

/**
 * Verifies that scanning an empty filesystem produces an empty list.
 */
function testEmptySourceList() {
  assertThrows(
    function() {
      scanner.scanFiles([]);
    });
}

function testIsScanning(callback) {
  var filenames = [
    'happy',
    'thoughts'
  ];
  reportPromise(
      makeTestFileSystemRoot('testIsScanning')
          .then(populateDir.bind(null, filenames))
          .then(
              /**
               * Scans the directory.
               * @param {!DirectoryEntry} root
               */
              function(root) {
                var results = scanner.scanDirectory(root);
                assertFalse(results.isFinal());
              }),
      callback);
}

function testObserverNotifiedOnScanFinish(callback) {
  var filenames = [
    'happy',
    'thoughts'
  ];
  makeTestFileSystemRoot('testObserverNotifiedOnScanFinish')
      .then(populateDir.bind(null, filenames))
      .then(
          /**
           * Scans the directory.
           * @param {!DirectoryEntry} root
           */
          function(root) {
            // Kick off a scan so we can get notified of a scan being finished.
            // We kick this off first so we can capture the result for
            // use in an assert. Promises ensure the scan won't finish
            // until after our funciton is fully processed.
            var result = scanner.scanDirectory(root);
            scanner.addObserver(
                function(eventType, scanResult) {
                  assertEquals(importer.ScanEvent.FINALIZED, eventType);
                  assertEquals(result, scanResult);
                  callback(false);
                });
          })
      .catch(
          function() {
            callback(true);
          });
}

/**
 * Verifies that scanFiles slurps up all specified files.
 */
function testScanFiles(callback) {
  var filenames = [
    'foo',
    'foo.jpg',
    'bar.gif',
    'baz.avi'
  ];
  var expectedFiles = [
    '/testScanFiles/foo.jpg',
    '/testScanFiles/bar.gif',
    '/testScanFiles/baz.avi'
  ];
  reportPromise(
      makeTestFileSystemRoot('testScanFiles')
          .then(populateDir.bind(null, filenames))
          .then(fileOperationUtil.gatherEntriesRecursively)
          .then(
              /** @param {!Array<!FileEntry>} files */
              function(files) {
                return scanner.scanFiles(files).whenFinal();
              })
          .then(assertFilesFound.bind(null, expectedFiles)),
      callback);
}

/**
 * Verifies that scanFiles skips duplicated files.
 */
function testScanFilesIgnoresPreviousImports(callback) {
  var filenames = [
    'oldimage1234.jpg',    // a history duplicate
    'driveimage1234.jpg',  // a content duplicate
    'foo.jpg',
    'bar.gif',
    'baz.avi'
  ];

  // Replace the default dispositionChecker with a function
  // that treats our dupes accordingly.
  dispositionChecker = function(entry, destination) {
    if (entry.name === filenames[0]) {
      return Promise.resolve(importer.Disposition.HISTORY_DUPLICATE);
    }
    if (entry.name === filenames[1]) {
      return Promise.resolve(importer.Disposition.CONTENT_DUPLICATE);
    }
    return Promise.resolve(importer.Disposition.ORIGINAL);
  };

  var expectedFiles = [
    '/testScanFilesIgnoresPreviousImports/foo.jpg',
    '/testScanFilesIgnoresPreviousImports/bar.gif',
    '/testScanFilesIgnoresPreviousImports/baz.avi'
  ];
  reportPromise(
      makeTestFileSystemRoot('testScanFilesIgnoresPreviousImports')
          .then(populateDir.bind(null, filenames))
          .then(fileOperationUtil.gatherEntriesRecursively)
          .then(
              /** @param {!Array<!FileEntry>} files */
              function(files) {
                return scanner.scanFiles(files).whenFinal();
              })
          .then(assertFilesFound.bind(null, expectedFiles)),
      callback);
}

/**
 * Verifies that scanning a simple single-level directory structure works.
 */
function testEmptyScanResults(callback) {
  var filenames = [
    'happy',
    'thoughts'
  ];
  reportPromise(
      makeTestFileSystemRoot('testEmptyScanResults')
          .then(populateDir.bind(null, filenames))
          .then(
              /**
               * Scans the directory.
               * @param {!DirectoryEntry} root
               */
              function(root) {
                return scanner.scanDirectory(root).whenFinal();
              })
          .then(assertFilesFound.bind(null, [])),
      callback);
}

/**
 * Verifies that scanning a simple single-level directory structure works.
 */
function testSingleLevel(callback) {
  var filenames = [
    'foo',
    'foo.jpg',
    'bar.gif',
    'baz.avi',
    'foo.mp3',
    'bar.txt'
  ];
  var expectedFiles = [
    '/testSingleLevel/foo.jpg',
    '/testSingleLevel/bar.gif',
    '/testSingleLevel/baz.avi'
  ];
  reportPromise(
      makeTestFileSystemRoot('testSingleLevel')
          .then(populateDir.bind(null, filenames))
          .then(
              /**
               * Scans the directory.
               * @param {!DirectoryEntry} root
               */
              function(root) {
                return scanner.scanDirectory(root).whenFinal();
              })
          .then(assertFilesFound.bind(null, expectedFiles)),
      callback);
}

/**
 * Verifies that scanning a simple single-level directory produces 100%
 * progress at completion.
 */
function testProgress(callback) {
  var filenames = [
    'foo',
    'foo.jpg',
    'bar.gif',
    'baz.avi',
    'foo.mp3',
    'bar.txt'
  ];
  var expectedFiles = [
    '/testProgress/foo.jpg',
    '/testProgress/bar.gif',
    '/testProgress/baz.avi'
  ];
  reportPromise(
      makeTestFileSystemRoot('testProgress')
          .then(populateDir.bind(null, filenames))
          .then(
              /**
               * Scans the directory.
               * @param {!DirectoryEntry} root
               */
              function(root) {
                return scanner.scanDirectory(root).whenFinal();
              })
          .then(assertProgress.bind(null, 100)),
      callback);
}

/**
 * Verifies that scanning ignores previously imported entries.
 */
function testIgnoresPreviousImports(callback) {
  importHistory.importedPaths[
      '/testIgnoresPreviousImports/oldimage1234.jpg'] =
          [importer.Destination.GOOGLE_DRIVE];
  var filenames = [
    'oldimage1234.jpg',    // a history duplicate
    'driveimage1234.jpg',  // a content duplicate
    'foo.jpg',
    'bar.gif',
    'baz.avi'
  ];

  // Replace the default dispositionChecker with a function
  // that treats our dupes accordingly.
  dispositionChecker = function(entry, destination) {
    if (entry.name === filenames[0]) {
      return Promise.resolve(importer.Disposition.HISTORY_DUPLICATE);
    }
    if (entry.name === filenames[1]) {
      return Promise.resolve(importer.Disposition.CONTENT_DUPLICATE);
    }
    return Promise.resolve(importer.Disposition.ORIGINAL);
  };

  var expectedFiles = [
    '/testIgnoresPreviousImports/foo.jpg',
    '/testIgnoresPreviousImports/bar.gif',
    '/testIgnoresPreviousImports/baz.avi'
  ];

  var promise = makeTestFileSystemRoot('testIgnoresPreviousImports')
      .then(populateDir.bind(null, filenames))
      .then(
          /**
           * Scans the directory.
           * @param {!DirectoryEntry} root
           */
          function(root) {
            return scanner.scanDirectory(root).whenFinal();
          })
      .then(assertFilesFound.bind(null, expectedFiles))

  reportPromise(promise, callback);
}

function testTracksDuplicates(callback) {
  importHistory.importedPaths[
      '/testTracksDuplicates/oldimage1234.jpg'] =
          [importer.Destination.GOOGLE_DRIVE];
  var filenames = [
    'oldimage1234.jpg',    // a history duplicate
    'driveimage1234.jpg',  // a content duplicate
    'driveimage9999.jpg',  // a content duplicate
    'bar.gif',
    'baz.avi'
  ];

  // Replace the default dispositionChecker with a function
  // that treats our dupes accordingly.
  dispositionChecker = function(entry, destination) {
    if (entry.name === filenames[0]) {
      return Promise.resolve(importer.Disposition.HISTORY_DUPLICATE);
    }
    if (entry.name === filenames[1]) {
      return Promise.resolve(importer.Disposition.CONTENT_DUPLICATE);
    }
    if (entry.name === filenames[2]) {
      return Promise.resolve(importer.Disposition.CONTENT_DUPLICATE);
    }
    return Promise.resolve(importer.Disposition.ORIGINAL);
  };

  var expectedDuplicates = [
    '/testTracksDuplicates/driveimage1234.jpg',
    '/testTracksDuplicates/driveimage9999.jpg'
  ];

  var promise = makeTestFileSystemRoot('testTracksDuplicates')
      .then(populateDir.bind(null, filenames))
      .then(
          /**
           * Scans the directory.
           * @param {!DirectoryEntry} root
           */
          function(root) {
            return scanner.scanDirectory(root).whenFinal();
          })
      .then(assertDuplicatesFound.bind(null, expectedDuplicates));

  reportPromise(promise, callback);
}

function testMultiLevel(callback) {
  var filenames = [
    'foo.jpg',
    'bar',
    [
      'dir1',
      'bar.0.jpg'
    ],
    [
      'dir2',
      'bar.1.gif',
      [
        'dir3',
        'bar.1.0.avi'
      ]
    ]
  ];
  var expectedFiles = [
    '/testMultiLevel/foo.jpg',
    '/testMultiLevel/dir1/bar.0.jpg',
    '/testMultiLevel/dir2/bar.1.gif',
    '/testMultiLevel/dir2/dir3/bar.1.0.avi'
  ];

  reportPromise(
      makeTestFileSystemRoot('testMultiLevel')
          .then(populateDir.bind(null, filenames))
          .then(
              /**
               * Scans the directory.
               * @param {!DirectoryEntry} root
               */
              function(root) {
                return scanner.scanDirectory(root).whenFinal();
              })
          .then(assertFilesFound.bind(null, expectedFiles)),
      callback);
}

function testDedupesFilesInScanResult(callback) {
  var filenames = [
    'foo.jpg',
    'bar.jpg',
    [
      'dir1',
      'foo.jpg',
      'bar.jpg'
    ],
    [
      'dir2',
      'foo.jpg',
      'bar.jpg',
      [
        'dir3',
        'foo.jpg',
        'bar.jpg'
      ]
    ]
  ];
  var expectedFiles = [
    '/testDedupesFilesInScanResult/foo.jpg',
    '/testDedupesFilesInScanResult/bar.jpg'
  ];

  reportPromise(
      makeTestFileSystemRoot('testDedupesFilesInScanResult')
          .then(populateDir.bind(null, filenames))
          .then(
              /**
               * Scans the directory.
               * @param {!DirectoryEntry} root
               */
              function(root) {
                return scanner.scanDirectory(root).whenFinal();
              })
          .then(assertFilesFound.bind(null, expectedFiles)),
      callback);
}

/**
 * Verifies that scanning a simple single-level directory structure works.
 */
function testDefaultScanResult() {
  var hashGenerator = function(file) {
    return file.toURL();
  };
  var scan = new importer.DefaultScanResult(hashGenerator);

  // 0 before we set candidate count
  assertProgress(0, scan);

  scan.setCandidateCount(3);
  assertProgress(0, scan);

  scan.onCandidatesProcessed(1);
  assertProgress(33, scan);
  scan.onCandidatesProcessed(1);
  assertProgress(66, scan);
  scan.onCandidatesProcessed(1);
  assertProgress(100, scan);
}

function testInvalidation(callback) {
  var invalidatePromise = new Promise(function(fulfill) {
    scanner.addObserver(fulfill);
  });
  reportPromise(
      makeTestFileSystemRoot('testInvalidation')
          .then(populateDir.bind(null, ['DCIM']))
          .then(
              /**
               * Scans the directories.
               * @param {!DirectoryEntry} root
               */
              function(root) {
                scan = scanner.scanDirectory(root);
                watcher.callback();
                return invalidatePromise;
              }),
              callback);
}

/**
 * Verifies the results of the media scan are as expected.
 * @param {number} expected, 0-100
 * @param {!importer.ScanResults} scan
 * @return {!importer.ScanResults}
 */
function assertProgress(expected, scan) {
  assertEquals(expected, scan.getStatistics().progress);
  return scan;
}

/**
 * Verifies the results of the media scan are as expected.
 * @param {!Array<string>} expected
 * @param {!importer.ScanResults} scan
 * @return {!importer.ScanResults}
 */
function assertFilesFound(expected, scan) {
  assertFileEntryPathsEqual(expected, scan.getFileEntries());
  return scan;
  // TODO(smckay): Add coverage for getScanDurationMs && getTotalBytes.
}

/**
 * Verifies the results of the media scan are as expected.
 * @param {!Array<string>} expected
 * @param {!importer.ScanResults} scan
 * @return {!importer.ScanResults}
 */
function assertDuplicatesFound(expected, scan) {
  assertFileEntryPathsEqual(expected, scan.getDuplicateFileEntries());
  return scan;
}

/**
 * Creates a subdirectory within a temporary file system for testing.
 *
 * @param {string} directoryName Name of the test directory to create.  Must be
 *     unique within this test suite.
 */
function makeTestFileSystemRoot(directoryName) {
  function makeTestFilesystem() {
    return new Promise(function(resolve, reject) {
      window.webkitRequestFileSystem(
          window.TEMPORARY,
          1024 * 1024,
          resolve,
          reject);
    });
  }

  return makeTestFilesystem()
      .then(
          // Create a directory, pretend that's the root.
          function(fs) {
            return new Promise(function(resolve, reject) {
              fs.root.getDirectory(
                    directoryName,
                    {
                      create: true,
                      exclusive: true
                    },
                  resolve,
                  reject);
            });
          });
}

/**
 * Creates a set of files in the given directory.
 * @param {!Array<!Array|string>} filenames A (potentially nested) array of
 *     strings, reflecting a directory structure.
 * @param {!DirectoryEntry} dir The root of the directory tree.
 * @return {!Promise.<!DirectoryEntry>} The root of the newly populated
 *     directory tree.
 */
function populateDir(filenames, dir) {
  return Promise.all(
      filenames.map(
          function(filename) {
            if (filename instanceof Array) {
              return new Promise(
                  function(resolve, reject) {
                    dir.getDirectory(
                        filename[0],
                        {create: true},
                        resolve,
                        reject);
                  })
                  .then(populateDir.bind(null, filename));
            } else {
              return new Promise(
                  function(resolve, reject) {
                    dir.getFile(filename, {create: true}, resolve, reject);
                  });
            }
          })).then(
              function() {
                return dir;
              });
}

redpajama_set_name: RedPajamaGithub


text:
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**partyIdentifier** | **String** | An identifier for the Party that is unique within a given context.. | [optional]
**addresses** | [**[Address1]**](Address1.md) | An array of the Party's addresses. | [optional]
**description** | **String** | An optional description of the Party. | [optional] [default to 'null']
**preferences** | [**[Preferences]**](Preferences.md) | A list of Preferences associated with the Party. | [optional]
**registeredIds** | [**[RegisteredIdentifier1]**](RegisteredIdentifier1.md) | An identifier for a Party that has been assigend by a recognized or statutory body. | [optional]
**dateOfBirth** | **Date** | The Person's date of birth. | [optional]
**ethnicities** | [**[PeopleEthnicities]**](PeopleEthnicities.md) |  | [optional]
**gender** | [**PeopleGender**](PeopleGender.md) |  | [optional]
**isoSex** | [**PeopleIsoSex**](PeopleIsoSex.md) |  | [optional]
**personName** | [**PersonName1**](PersonName1.md) |  | [optional]
**otherPersonNames** | [**[PersonName1]**](PersonName1.md) |  | [optional]


text:
<!DOCTYPE html>

<html class="height-all">
    <head>
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=medium-dpi" />

        <link rel="stylesheet" type="text/css" href="css/lib/bootstrap.css" />
        <link rel="stylesheet" type="text/css" href="css/views/index.css" />
        <link rel="stylesheet" type="text/css" href="css/views/index.player-list.css" />
        <link rel="stylesheet" type="text/css" href="css/views/index.player-details.css" />
        <link rel="stylesheet" type="text/css" href="css/views/index.player-bio.css" />
        <link rel="stylesheet" type="text/css" href="css/views/index.kombatkodes.css" />
        <title>MK Moves</title>
    </head>
    <body class="height-all">
        <div id="content" class="height-all">
        </div>

        <script src="cordova.js"></script>
        <script src="js/lib/jquery.js"></script>
        <script src="js/lib/bootstrap.js"></script>
        <script src="js/lib/underscore.js"></script>
        <script src="js/lib/sammy.js"></script>
        <script src="js/lib/knockout.js"></script>
        <script src="js/data.js"></script>
        <script src="js/loaders/templateFromUrlLoader.js"></script>
        <script src="js/services/DataFixer.js"></script>
        <script src="js/services/DataService.js"></script>
        <script src="js/services/UserSettings.js"></script>
        <script src="js/bindings/ElementBinding.js"></script>
        <script src="js/viewModels/PlayerListViewModel.js"></script>
        <script src="js/viewModels/PlayerDetailsViewModel.js"></script>
        <script src="js/viewModels/MoveViewModel.js"></script>
        <script src="js/viewModels/MoveGroupViewModel.js"></script>
        <script src="js/viewModels/ButtonViewModel.js"></script>
        <script src="js/viewModels/KombatKodesViewModel.js"></script>
        <script src="js/viewModels/PlayerBioViewModel.js"></script>
        <script src="js/viewModels/PlayerViewModel.js"></script>
        <script src="js/components/mk-move.js"></script>
        <script src="js/components/mk-move-group.js"></script>
        <script src="js/components/mk-button.js"></script>
        <script>
            var app = Sammy('#content', function() {
                this.get('#/player-list', function() {
                    this.load('html/views/player-list.html').swap();
                });

                this.get('#/player-grid', function() {
                    this.load('html/views/player-grid.html').swap();
                });

                this.get('#/player-details/:playerId', function() {
                    window.routeParams = window.routeParams || {};
                    window.routeParams.playerId = this.params['playerId'];

                    this.load('html/views/player-details.html').swap();
                });

                this.get('#/kombatkodes', function() {
                    this.load('html/views/kombatkodes.html').swap();
                });

                this.get('#/player-bio/:playerId', function() {
                    window.routeParams = window.routeParams || {};
                    window.routeParams.playerId = this.params['playerId'];

                    this.load('html/views/player-bio.html').swap();
                });

                this.notFound = function() {
                    this.setLocation("#/player-list");
                }
            });

            $(document).ready(function() {
                app.run('#/player-list');
            });
        </script>
    </body>
</html>


text:
package breeze.corpora;

//import breeze.util.Implicits._;
import java.net._;
import java.io.File;
import scala.xml.XML;

/**
* Class to help load corpora. Each Corpus is represented by a class
* of type "Corpus" which knows how to load the data.
*
* Corpora are located in one of two ways:
*

*
 Provide a class name for the corpus for a class already in the class path.

*
2) Located through one or more public repositories, usually your
*     MAVEN_HOME and the breeze maven repository.
*
*     Files located in this way must be installed in:
*      /path/to/repository/org/breeze/corpora/(corpus name in lower case)/(version)/(corpus-name)-(version).jar
*
*     The jar file itself must have a file named breeze-corpus.xml which has the format:
*
*       <corpus>
*         <classname>absolute classname</classname>
*       </corpus>
*
*    This class is then created and returned.
*

*

*
* @author dlwh
*/
class Corpora(val repositories: Seq[URL]) {
  import Corpora._;
  def this(remoteURL: String) = this( Array(CorpusUtils.defaultCorpusRepo, new URL(remoteURL)));

  /**
  * Create a new instance of the corpus.
  */
  def load[T](clss: Class[U] forSome {type U<:Corpus[T]}) = {
    clss.newInstance;
  }

  /**
  * Either loads the Corpus with the given class name, or searches the repositories for the corpus with the (lowercase) name.
  */
  def load[T](name: String):Corpus[T] = {
    val clss = cForName[T](name) orElse cForName[T]("breeze.corpora."+name);
    clss match {
      case None => locateCorpus(name);
      case Some(c) => load(c.asSubclass(classOf[Corpus[T]]))
    }
  }

  /**
  * Searches for a corpus in the available repositories.
  */
  def locateCorpus[T](name: String) : Corpus[T] = {
    val jarLocation = findJar(name);
    val cl = new URLClassLoader(Array(jarLocation));
    val className = {
      val strm = cl.getResourceAsStream("breeze-corpus.xml");
      val xml = XML.load(strm);
      println(xml);
      strm.close();
      (xml \ "classname").text.trim();
    }
    println(className + " " + jarLocation);
    load(cl.loadClass(className).asSubclass(classOf[Corpus[T]]));
  }

  private def findJar(name: String) = {
    val lowerName = name.toLowerCase;
    val urls = repositories.iterator;

    var jar: URL = null;
    while(urls.hasNext && (jar eq null)) {
      val url = urls.next;
      try { // is it a directory?
        val f = new File(url.toURI);
        val location = new File(new File(f, "org/breeze/corpora/"), lowerName);
        println(location);
        if(location.exists && location.isDirectory) {
          val latestVersion = location.listFiles.filter(_.isDirectory).reduceLeft( (x,y) =>
            new File(lexicographicOrder(x.getName,y.getName))
          );
          println(latestVersion);
          jar = latestVersion.listFiles.filter(_.getName.endsWith(".jar"))(0).toURI.toURL
        }
      } catch { // not a file, so we'll hope it's a maven repo
        case _ =>
        val location = url.toString +"/org/breeze/corpora/"+lowerName;
        val metadata = new URL(location + "/maven-metadata.xml");
        try {
          val stream = metadata.openStream();
          try {
            val xml = XML.load(stream);
            val latestVersion = (xml \ "version").text
            jar = new URL(location + "/" + latestVersion + "/"+lowerName + "-"+latestVersion + ".jar");
          } finally {
            stream.close();
          }
        } catch {
          case _ => ();
        }
      }
    }
    if(jar == null) throw new RuntimeException("Couldn't find the corpus " + name);
    jar
  }

  private def lexicographicOrder(f1: String, f2: String) = {
    if(f1.split(".").zip(f2.split(".")).forall { case (s1,s2) =>
      try {
        s1.toInt > s2.toInt
      } catch {
        case _ => s1 > s2;
      }
    }) f1 else f2;
  }

  private def cForName[T](name: String) = try {
    Some(Class.forName(name).asInstanceOf[Class[Corpus[T]]])
  } catch {
    case _ => None;
  }

}

object Corpora extends Corpora("http://repo.breeze.org/repo/") {
}

object CorpusUtils {
  protected[corpora] def defaultCorpusRepo = {
    val repoFile = {
      var a = System.getenv("SCALANLP_CORPORA");
      if(a == null) a = System.getenv("MAVEN_HOME");
      if(a == null) a = System.getenv("HOME") + "/.m2/"
    a } + "repository/";
    new File(repoFile).toURI.toURL;
  }

}


text:
/**
 * syr2k.h: This file is part of the PolyBench 3.0 test suite.
 *
 *
 * Contact: Louis-Noel Pouchet <pouchet@cse.ohio-state.edu>
 * Web address: http://polybench.sourceforge.net
 */
#ifndef SYR2K_H
# define SYR2K_H

/* Default to STANDARD_DATASET. */
# if !defined(MINI_DATASET) && !defined(SMALL_DATASET) && !defined(LARGE_DATASET) && !defined(EXTRALARGE_DATASET)
#  define STANDARD_DATASET
# endif

/* Do not define anything if the user manually defines the size. */
# if !defined(NI) && !defined(NJ)
/* Define the possible dataset sizes. */
#  ifdef MINI_DATASET
#   define NI 32
#   define NJ 32
#  endif

#  ifdef SMALL_DATASET
#   define NI 128
#   define NJ 128
#  endif

#  ifdef STANDARD_DATASET /* Default if unspecified. */
#   define NI 1024
#   define NJ 1024
#  endif

#  ifdef LARGE_DATASET
#   define NI 2000
#   define NJ 2000
#  endif

#  ifdef EXTRALARGE_DATASET
#   define NI 4000
#   define NJ 4000
#  endif
# endif /* !N */

# ifndef DATA_TYPE
#  define DATA_TYPE double
#  define DATA_PRINTF_MODIFIER "%0.2lf "
# endif

#endif /* !SYR2K */