//
// $Id: AlgorithmTest.m,v 1.19 2005/05/18 06:46:55 will_mason Exp $
//
// vi: set ft=objc:

/*
 * ObjectiveLib - a library of containers and algorithms for Objective-C
 *
 * Copyright (c) 2004
 * Will Mason
 *
 * Portions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1997
 * Moscow Center for SPARC Technology
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * You may contact the author at will_mason@users.sourceforge.net.
 */

#import "AlgorithmTest.h"
#import <ObjectiveLib/Algorithm.h>
#import <ObjectiveLib/Vector.h>
#import <ObjectiveLib/List.h>
#import <ObjectiveLib/Deque.h>
#import <ObjectiveLib/Arithmetic.h>
#import <ObjectiveLib/Set.h>
#import <Foundation/NSString.h>
#if defined(GNUSTEP)
#import <ObjectiveLib/Comparison.h>
#else
#import <Foundation/NSScriptWhoseTests.h>
#endif
#import <Foundation/NSSet.h>
#import <Foundation/NSThread.h>
#import <stdlib.h>

static int __indexOf(OLArrayIterator* itor, OLVector* v)
{
    int i;
    int end = [v size];
    int num = [[itor dereference] intValue];

    for (i = 0; i < end; i++)
    {
        if ([[v at: i] intValue] == num)
            break;
    }
    return i;
}

@interface LessThanFive : NSObject <OLBoolUnaryFunction>
{
}

- (BOOL) performUnaryFunctionWithArg: (id)arg;

@end

@implementation LessThanFive

- (BOOL) performUnaryFunctionWithArg: (id)arg
{
    NSNumber* five = [[NSNumber alloc] initWithInt: 5];
    BOOL result = [arg isLessThan: five];

    [five release];
    return result;
}

@end

@interface AddDoggy : OLAllocFunctor <OLUnaryFunction>
{
}

- (id) performUnaryFunctionWithArg: (id)arg;

@end

@implementation AddDoggy

- (id) performUnaryFunctionWithArg: (id)arg
{
    [arg insertString: @"doggy" atIndex: 0];
    return nil;
}

@end

@interface RandomGen : OLAllocFunctor <OLUnaryFunction>
{
}

- (id) init;
- (void) dealloc;
- (id) performUnaryFunctionWithArg: (id)arg;

@end

@implementation RandomGen

- (id) init
{
    FILE* dev = fopen("/dev/random", "r");
    unsigned seed;

    [super initWithAutorelease: NO];
    if (dev != NULL)
    {
        fread(&seed, sizeof(unsigned), 1, dev);
        fclose(dev);
        srand(seed);
    }
    return self;
}

- (void) dealloc
{
    [super dealloc];
}

- (id) performUnaryFunctionWithArg: (id)arg
{
    return [[NSNumber alloc] initWithUnsignedInt: rand() % [arg unsignedIntValue]];
}

@end

@interface PartitionFunction : NSObject <OLBoolUnaryFunction>
{
@private
    int value;
}

- (id) initWithValue: (int)val;
- (BOOL) performUnaryFunctionWithArg: (id)arg;

@end


@implementation PartitionFunction

- (id) initWithValue: (int)val
{
    [super init];
    value = val;
    return self;
}

- (BOOL) performUnaryFunctionWithArg: (id)arg
{
    return [arg intValue] < value ? YES : NO;
}

@end

@interface FindIfFunction : NSObject <OLBoolUnaryFunction>
{
@private
    int value;
}

- (id) initWithValue: (int)val;
- (BOOL) performUnaryFunctionWithArg: (id)arg;

@end


@implementation FindIfFunction

- (id) initWithValue: (int)val
{
    [super init];
    value = val;
    return self;
}

- (BOOL) performUnaryFunctionWithArg: (id)arg
{
    return [arg intValue] == value ? YES : NO;
}

@end

@interface StrICmp : NSObject <OLBoolBinaryFunction>
{
}

- (BOOL) performBinaryFunctionWithArg: (id)arg1 andArg: (id)arg2;

@end

@implementation StrICmp

- (BOOL) performBinaryFunctionWithArg: (id)arg1 andArg: (id)arg2
{
    return [arg1 caseInsensitiveCompare: arg2] == NSOrderedSame ? YES : NO;
}

@end

@interface IntCompare : NSObject <OLBoolBinaryFunction>
{
}

- (BOOL) performBinaryFunctionWithArg: (id)arg1 andArg: (id)arg2;

@end

@implementation IntCompare

- (BOOL) performBinaryFunctionWithArg: (id)arg1 andArg: (id)arg2
{
    return [arg1 intValue] == [arg2 intValue];
}

@end

@interface AppendDoggy : OLAllocFunctor <OLUnaryFunction>
{
}

- (id) performUnaryFunctionWithArg: (id)arg;

@end

@implementation AppendDoggy

- (id) performUnaryFunctionWithArg: (id)arg
{
    NSString* result = [[allocator allocateObject: [NSString class]]
        initWithFormat: @"%@doggy", arg];

    if (autorelease)
        [allocator autorelease: result];
    return result;
}

@end

@interface AppendOther : OLAllocFunctor <OLBinaryFunction>
{
}

-(id) performBinaryFunctionWithArg: (id)arg1 andArg: (id)arg2;

@end

@implementation AppendOther

-(id) performBinaryFunctionWithArg: (id)arg1 andArg: (id)arg2
{
    NSString* result = [[allocator allocateObject: [NSString class]]
        initWithFormat: @"%@%@", arg1, arg2];

    if (autorelease)
        [allocator autorelease: result];
    return result;
}

@end

@implementation AlgorithmTest

- (void) runSecondThread: (id)arg
{
    if ([OLAlgorithm allocator] == arg)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The OLAlgorithm class should have a different allocator for each thread"];
    }
}

- (void) testAdjacentFind
{
    OLList* l;
    NSNumber* num;
    OLForwardIterator* r;
    int nums[] = { 1, 2, 3, 4, 5, 5, 6, 7 };
    int i;

    l = [[OLList alloc] init];
    for (i = 0; i < 8; i++)
    {
        num = [[NSNumber alloc] initWithInt: nums[i]];
        [l pushBack: num];
        [num release];
    }
    r = [OLAlgorithm adjacentFindFrom: [l begin] to: [l end]];
    if ([[r dereference] intValue] != 5)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 5, but got %i", [[r dereference] intValue]];
    }
    if ([[[r advance] dereference] intValue] != 5)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 5, but got %i", [[r dereference] intValue]];
    }
    [l erase: (OLListIterator*)r];
    r = [OLAlgorithm adjacentFindFrom: [l begin] to: [l end]];
    if (![r isEqual: [l end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The iterator should be at the end"];
    }
    [l release];
}

- (void) testAllocatorThreading
{
    [NSThread detachNewThreadSelector: @selector(runSecondThread:)
        toTarget: self withObject: [OLAlgorithm allocator]];
}

- (void) testBinarySearch
{
    OLList* l;
    NSNumber* num;
    int i;
    OLGreater* greater;
    OLListIterator* b;
    OLListIterator* e;

    l = [[OLList alloc] init];
    for (i = 0; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    [l sort];
    b = [l begin];
    e = [l end];
    if (![OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 30]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if (![OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 70]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if (![OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 99]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if (![OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 0]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if ([OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: -100]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if ([OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 1000]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    greater = [[OLGreater alloc] init];
    [l sortWith: greater];
    b = [l begin];
    e = [l end];
    if (![OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 30] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if (![OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 70] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if (![OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 99] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if (![OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 0] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if ([OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: -100] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    if ([OLAlgorithm binarySearchFrom: b to: e
            value: [NSNumber numberWithInt: 1000] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number 30 should have been found"];
    }
    [greater release];
    [l release];
}

- (void) testCopy
{
    NSString* strs[] = { @"zero", @"zero", @"one", @"two", @"three", @"four", @"five", @"six", @"six" };
    int i;
    OLVector* v;
    OLPair* p;
    OLList* l;
    OLForwardIterator* r;
    OLListIterator* end;
    OLListIterator* itor;

    v = [[OLVector alloc] init];
    p = [OLArrayIterator pairWithPointer: strs + 2 andPointer: strs + 7];
    [v insertAt: [v begin] from: [p first] to: [p second]];
    l = [[OLList alloc] initWithSize: 5 filledWith: @"doggy"];
    r = [OLAlgorithm copyFrom: [v begin] to: [v end] destination: [l begin]];
    end = [l end];
    if (![r isEqual: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The resulting iterator should be the end of the list"];
    }
    for (itor = [l begin], i = 2; ![itor isEqual: end]; [itor advance], i++)
    {
        if (![[itor dereference] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[itor dereference] cString]];
        }
    }
    [l pushBack: @"six"];
    r = [OLAlgorithm copyFrom: [[l begin] advance] to: [l end] destination: [l begin]];
    end = [l end];
    if (![r isEqual: [end reverse]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The resulting iterator is wrong"];
    }
    [end advance];
    for (itor = [l begin], i = 3; ![itor isEqual: end]; [itor advance], i++)
    {
        if (![[itor dereference] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[itor dereference] cString]];
        }
    }
    [l assign: 5 filledWith: @"doggy"];
    r = [OLAlgorithm copyBackwardFrom: [v begin] to: [v end] destination: [l end]];
    if (![r isEqual: [l begin]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The resulting iterator should be the end of the list"];
    }
    end = [l end];
    for (itor = [l begin], i = 2; ![itor isEqual: end]; [itor advance], i++)
    {
        if (![[itor dereference] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[itor dereference] cString]];
        }
    }
    [l pushFront: @"zero"];
    r = [OLAlgorithm copyBackwardFrom: [l begin] to: [[l end] reverse] destination: [l end]];
    if (![r isEqual: [[l begin] advance]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The resulting iterator is wrong"];
    }
    end = [l end];
    for (itor = [l begin], i = 0; ![itor isEqual: end]; [itor advance], i++)
    {
        if (![[itor dereference] isEqual: strs[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"%s\", but got \"%s\"",
                [strs[i] cString], [[itor dereference] cString]];
        }
    }
    [l release];
    [v release];
}

- (void) testCounting
{
    OLList* l;
    NSNumber* num;
    NSNumber* target;
    LessThanFive* lessThanFive;
    int nums[] = { 5, 1, 2, 3, 4, 5, 6, 7, 8, 5 };
    int i;
    unsigned count;

    l = [[OLList alloc] init];
    for (i = 0; i < 10; i++)
    {
        num = [[NSNumber alloc] initWithInt: nums[i]];
        [l pushBack: num];
        [num release];
    }
    target = [NSNumber numberWithInt: 5];
    count = [OLAlgorithm countFrom: [l begin] to: [l end] value: target];
    if (count != 3)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 3, but got %i", count];
    }
    target = [NSNumber numberWithInt: 1];
    count = [OLAlgorithm countFrom: [l begin] to: [l end] value: target];
    if (count != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %i", count];
    }
    target = [NSNumber numberWithInt: -27];
    count = [OLAlgorithm countFrom: [l begin] to: [l end] value: target];
    if (count != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %i", count];
    }
    lessThanFive = [[LessThanFive alloc] init];
    count = [OLAlgorithm countFrom: [l begin] to: [l end] predicate: lessThanFive];
    [lessThanFive release];
    if (count != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %i", count];
    }
    [l release];
}

- (void) testEqual
{
    OLVector* v;
    OLList* l;
    NSNumber* num;
    IntCompare* comp;
    int i;
    double i2;

    v = [[OLVector alloc] init];
    l = [[OLList alloc] init];
    for (i = 0; i < 3000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [l pushBack: num];
        [num release];
    }
    if (![OLAlgorithm equalFrom: [v begin] to: [v end] with: [l begin]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should be equal"];
    }
    num = [[NSNumber alloc] initWithInt: 75];
    [v insertAt: [[v begin] advanceBy: 2001] value: num];
    [num release];
    [v popBack];
    if ([OLAlgorithm equalFrom: [v begin] to: [v end] with: [l begin]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should not be equal"];
    }
    [v clear];
    [l clear];
    for (i2 = 0.0; i2 < 3000.0; i2++)
    {
        num = [[NSNumber alloc] initWithDouble: i2];
        [v pushBack: num];
        [num release];
        num = [[NSNumber alloc] initWithDouble: i2 + 0.4];
        [l pushBack: num];
        [num release];
    }
    comp = [[IntCompare alloc] init];
    if (![OLAlgorithm equalFrom: [v begin] to: [v end] with: [l begin] predicate: comp])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should be equal"];
    }
    num = [[NSNumber alloc] initWithDouble: 75.0];
    [v insertAt: [[v begin] advanceBy: 2001] value: num];
    [num release];
    [v popBack];
    if ([OLAlgorithm equalFrom: [v begin] to: [v end] with: [l begin] predicate: comp])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should not be equal"];
    }
    [comp release];
    [v release];
    [l release];
}

- (void) testEqualRange
{
    OLDeque* d;
    OLPair* p;
    NSNumber* num;
    OLGreater* greater;
    int nums[] = { 0, 1, 2, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10 };
    int i;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 13; i++)
    {
        num = [[NSNumber alloc] initWithInt: nums[i]];
        [d pushBack: num];
        [num release];
    }
    num = [[NSNumber alloc] initWithInt: 3];
    p = [OLAlgorithm equalRangeFrom: [d begin] to: [d end] value: num];
    if ([[[p second] dereference] intValue] != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %i", [[[p second] dereference] intValue]];
    }
    if ([OLIterator distanceFrom: [p first] to: [p second]] != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %i",
            [OLIterator distanceFrom: [p first] to: [p second]]];
    }
    while (![[p first] isEqual: [p second]])
    {
        if ([[[p first] dereference] intValue] != 3)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected 3, but got %i", [[[p first] dereference] intValue]];
        }
        [[p first] advance];
    }
    greater = [[OLGreater alloc] init];
    [OLAlgorithm sortFrom: [d begin] to: [d end] predicate: greater];
    p = [OLAlgorithm equalRangeFrom: [d begin] to: [d end] value: num predicate: greater];
    [greater release];
    [num release];
    if ([[[p second] dereference] intValue] != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %i", [[[p second] dereference] intValue]];
    }
    if ([OLIterator distanceFrom: [p first] to: [p second]] != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %i",
            [OLIterator distanceFrom: [p first] to: [p second]]];
    }
    while (![[p first] isEqual: [p second]])
    {
        if ([[[p first] dereference] intValue] != 3)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected 3, but got %i", [[[p first] dereference] intValue]];
        }
        [[p first] advance];
    }
    [d release];
}

- (void) testFill
{
    OLDeque* d;
    NSNumber* num;
    NSString* filled = @"doggy";
    OLDequeIterator* fillTo;
    int i;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 20; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    fillTo = [[d begin] advanceBy: 7];
    [OLAlgorithm fillFrom: [d begin] to: fillTo value: filled];
    for (i = 0; i < 7; i++)
    {
        if (![[d at: i] isEqual: filled])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"",
                [[d at: i] cString]];
        }
    }
    for ( ; i < 20; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[d at: i] intValue]];
        }
    }
    [OLAlgorithm fillFrom: [fillTo advanceBy: 3] count: 4 value: filled];
    for (i = 10; i < 14; i++)
    {
        if (![[d at: i] isEqual: filled])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected \"doggy\", but got \"%s\"",
                [[d at: i] cString]];
        }
    }
    for ( ; i < 20; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[d at: i] intValue]];
        }
    }
    [d release];
}

- (void) testFind
{
    OLList* l;
    OLForwardIterator* r;
    OLListIterator* begin;
    OLListIterator* end;
    NSNumber* num;
    FindIfFunction* func;
    int i;

    l = [[OLList alloc] init];
    for (i = 0; i < 1000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    num = [[NSNumber alloc] initWithInt: 726];
    begin = [l begin];
    end = [l end];
    r = [OLAlgorithm findFrom: begin to: end value: num];
    [num release];
    if ([r isEqual: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should have been found"];
    }
    if ([[r dereference] intValue] != 726)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 726, but got %i", [[r dereference] intValue]];
    }
    num = [[NSNumber alloc] initWithInt: -324];
    r = [OLAlgorithm findFrom: begin to: end value: num];
    [num release];
    if (![r isEqual: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should not have been found"];
    }
    func = [[FindIfFunction alloc] initWithValue: 524];
    r = [OLAlgorithm findFrom: begin to: end if: func];
    [func release];
    if ([r isEqual: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should have been found"];
    }
    if ([[r dereference] intValue] != 524)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 524, but got %i", [[r dereference] intValue]];
    }
    func = [[FindIfFunction alloc] initWithValue: 6024];
    r = [OLAlgorithm findFrom: begin to: end if: func];
    [func release];
    if (![r isEqual: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should not have been found"];
    }
    [l release];
}

- (void) testFindEnd
{
    OLDeque* d;
    OLVector* v;
    NSNumber* num;
    OLForwardIterator* r;
    IntCompare* comp;
    OLDequeIterator* dbegin;
    OLDequeIterator* dend;
    int i;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 1000; i++)
    {
        num = [[NSNumber alloc] initWithDouble: i + .5];
        [d pushBack: num];
        [num release];
    }
    v = [[OLVector alloc] init];
    for (i = 784; i < 899; i++)
    {
        num = [[NSNumber alloc] initWithDouble: i + 0.5];
        [v pushBack: num];
        [d pushBack: num];
        [num release];
    }
    dbegin = [d begin];
    dend = [d end];
    r = [OLAlgorithm findEndFrom: dbegin to: dend subFrom: [v begin] subTo: [v end]];
    if ([r isEqual: dend])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should have been found"];
    }
    if ([[r dereference] doubleValue] != 784.5)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 784, but got %i", [[r dereference] intValue]];
    }
    if ([OLIterator distanceFrom: dbegin to: r] != 1000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Search found the last one, not the first one (distance %u)",
            [OLIterator distanceFrom: dbegin to: r]];
    }
    [v clear];
    for (i = 784; i < 899; i++)
    {
        num = [[NSNumber alloc] initWithDouble: i];
        [v pushBack: num];
        [num release];
    }
    comp = [[IntCompare alloc] init];
    r = [OLAlgorithm findEndFrom: dbegin to: dend subFrom: [v begin] subTo: [v end]
        predicate: comp];
    [comp release];
    if ([r isEqual: dend])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should have been found"];
    }
    if ([[r dereference] doubleValue] != 784.5)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 784, but got %i", [[r dereference] intValue]];
    }
    if ([OLIterator distanceFrom: dbegin to: r] != 1000)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Search found the last one, not the first one"];
    }
    [d release];
    [v release];
}

- (void) testFindFirst
{
    OLDeque* d;
    OLVector* v;
    NSNumber* num;
    OLForwardIterator* r;
    NSString* strs[] = { @"one", @"two", @"three", @"four", @"five" };
    NSString* strs2[] = { @"SIX", @"SEVEN", @"EIGHT", @"FIVE", @"TEN" };
    StrICmp* cmp;
    int i;
    int rand;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 1000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    v = [[OLVector alloc] init];
    for ( ; i < 1999; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    rand = lrand48() % 1000;
    num = [[NSNumber alloc] initWithInt: rand];
    [v pushBack: num];
    [num release];
    r = [OLAlgorithm findFirstFrom: [d begin] to: [d end] ofFrom: [v begin] ofTo: [v end]];
    if ([r isEqual: [d end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should have been found"];
    }
    if ([[r dereference] intValue] != rand)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %i, but got %i",
            rand, [[r dereference] intValue]];
    }
    [d clear];
    for (i = 0; i < 5; i++)
        [d pushBack: strs[i]];
    [v clear];
    for (i = 0; i < 5; i++)
        [v pushBack: strs2[i]];
    cmp = [[StrICmp alloc] init];
    r = [OLAlgorithm findFirstFrom: [d begin] to: [d end] ofFrom: [v begin] ofTo: [v end]
        predicate: cmp];
    [cmp release];
    if ([r isEqual: [d end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should have been found"];
    }
    if (![[r dereference] isEqual: @"five"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"five\", but got \"%i\"", [[r dereference] cString]];
    }
    [v erase: [[v end] advanceBy: -2]];
    r = [OLAlgorithm findFirstFrom: [d begin] to: [d end] ofFrom: [v begin] ofTo: [v end]];
    if (![r isEqual: [d end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should not have been found"];
    }
    [v release];
    [d release];
}

- (void) testForEach
{
    OLVector* v;
    AddDoggy* func;
    NSNumber* num;
    double i;
    int j;

    v = [[OLVector alloc] init];
    for (i = 0.0; i < 10000.0; i++)
    {
        num = [[NSMutableString alloc] initWithFormat: @"%G", i];
        [v pushBack: num];
        [num release];
    }
    func = [[AddDoggy alloc] init];
    [OLAlgorithm forEachFrom: [v begin] to: [v end] function: func];
    [func release];
    for (j = 0; j < 10000; j++)
    {
        if (![[v at: j] hasPrefix: @"doggy"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The stringn was not transformed"];
        }
    }
    [v release];
}

- (void) testIncludes
{
    OLDeque* d;
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    OLForwardIterator* ue;
    int i;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 20; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    v = [[OLVector alloc] init];
    for (i = 11; i < 15; i += 2)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    if (![OLAlgorithm includesFrom: [d begin] to: [d end] subFrom: [v begin] subTo: [v end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequence should have been found"];
    }
    [v clear];
    for (i = 18; i < 25; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    if ([OLAlgorithm includesFrom: [d begin] to: [d end] subFrom: [v begin] subTo: [v end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequence should not have been found"];
    }
    [d clear];
    [v clear];
    for (i = 9999; i >= 0; i--)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    for (i = 0; i < 500; i++)
    {
        num = [[NSNumber alloc] initWithInt: lrand48() % 10000];
        [v pushBack: num];
        [num release];
    }
    greater = [[OLGreater alloc] init];
    [OLAlgorithm sortFrom: [v begin] to: [v end] predicate: greater];
    ue = [OLAlgorithm uniqueFrom: [v begin] to: [v end]];
    if (![OLAlgorithm includesFrom: [d begin] to: [d end]
            subFrom: [v begin] subTo: ue predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequence should have been found"];
    }
    [v clear];
    for (i = 0; i < 5000; i++)
    {
        num = [[NSNumber alloc] initWithInt: (lrand48() % 10000) + 8000];
        [v pushBack: num];
        [num release];
    }
    [OLAlgorithm sortFrom: [v begin] to: [v end] predicate: greater];
    ue = [OLAlgorithm uniqueFrom: [v begin] to: [v end]];
    if ([OLAlgorithm includesFrom: [d begin] to: [d end]
            subFrom: [v begin] subTo: ue predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequence should not have been found (there is a sligh chance that this test will fail due to the random numbers involved)"];
    }
    [v release];
    [d release];
    [greater release];
}

- (void) testInPlaceMerge
{
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    OLArrayIterator* mid;
    int i;
    int next;

    v = [[OLVector alloc] init];
    for (i = 0; i < 20; i += 2)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    for (i = 1; i < 20; i += 2)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    [OLAlgorithm inPlaceMergeFrom: [v begin] middle: [[v begin] advanceBy: 10] to: [v end]];
    for (i = 0; i < 20; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    [v clear];
    for (i = 0; i < 20; i += 2)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    for ( ; i < 40; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    for (i = 1; i < 20; i += 2)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    [OLAlgorithm inPlaceMergeFrom: [v begin] middle: [[v begin] advanceBy: 30] to: [v end]];
    for (i = 0; i < 40; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    [v clear];
    for (i = 0; i < 20000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    [OLAlgorithm randomShuffleFrom: [v begin] to: [v end]];
    mid = [[v begin] advanceBy: lrand48() % 20000];
    greater = [[OLGreater alloc] init];
    [OLAlgorithm sortFrom: [v begin] to: mid predicate: greater];
    [OLAlgorithm sortFrom: mid to: [v end] predicate: greater];
    [OLAlgorithm inPlaceMergeFrom: [v begin] middle: mid to: [v end] predicate: greater];
    [greater release];
    for (i = 0, next = 1; next < 20000; i++, next++)
    {
        if ([[v at: next] intValue] > [[v at: i] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "[%i] %i should not be greater than [%i] %i",
                next, [[v at: next] intValue], i, [[v at: i] intValue]];
        }
    }
    [v release];
}

- (void) testLexicographicalCompare
{
    OLList* l;
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    int i;

    l = [[OLList alloc] init];
    v = [[OLVector alloc] init];
    for (i = 0; i < 5; i++)
    {
        if (i == 3)
        {
            num = [[NSNumber alloc] initWithInt: i + 1];
            [v pushBack: num];
            [num release];
            num = [[NSNumber alloc] initWithInt: i];
            [l pushBack: num];
            [num release];
        }
        else
        {
            num = [[NSNumber alloc] initWithInt: i];
            [l pushBack: num];
            [v pushBack: num];
            [num release];
        }
    }
    greater = [[OLGreater alloc] init];
    if (![OLAlgorithm lexicographicalCompareFrom: [l begin] to: [l end]
            andFrom: [v begin] andTo: [v end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "l should be less than v"];
    }
    if (![OLAlgorithm lexicographicalCompareFrom: [v begin] to: [v end]
            andFrom: [l begin] andTo: [l end] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "v should be greater than l"];
    }
    [v eraseFrom: [[v begin] advanceBy: 3] to: [v end]];
    if (![OLAlgorithm lexicographicalCompareFrom: [v begin] to: [v end]
            andFrom: [l begin] andTo: [l end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "v should be less than l"];
    }
    if ([OLAlgorithm lexicographicalCompareFrom: [l begin] to: [l end]
            andFrom: [v begin] andTo: [v end] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "l should not be greater than v"];
    }
    if (![OLAlgorithm lexicographicalCompareFrom: [v begin] to: [v end]
            andFrom: [l begin] andTo: [l end] predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "v should be greater than l"];
    }
    [v release];
    [l release];
    [greater release];
}

- (void) testLowerBound
{
    OLList* l;
    NSNumber* num;
    NSNumber* target;
    OLForwardIterator* r;
    OLGreater* greater;
    double i;

    l = [[OLList alloc] init];
    for (i = 0.0; i < 1000.0; i++)
    {
        num = [[NSNumber alloc] initWithDouble: i];
        [l pushBack: num];
        [num release];
    }
    target = [[NSNumber alloc] initWithDouble: 39.5];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target];
    [target release];
    if ([[r dereference] doubleValue] != 40.0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 40.0, but got %G", [[r dereference] doubleValue]];
    }
    target = [[NSNumber alloc] initWithDouble: 700];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target];
    [target release];
    if ([[r dereference] doubleValue] != 700.0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 700.0, but got %G", [[r dereference] doubleValue]];
    }
    target = [[NSNumber alloc] initWithDouble: 10000.0];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target];
    [target release];
    if (![r isEqual: [l end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected to be at the end"];
    }
    target = [[NSNumber alloc] initWithDouble: -10000.0];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target];
    [target release];
    if (![r isEqual: [l begin]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected to be at the beginning"];
    }
    greater = [[OLGreater alloc] init];
    [l sortWith: greater];
    target = [[NSNumber alloc] initWithDouble: 39.5];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target predicate: greater];
    [target release];
    if ([[r dereference] doubleValue] != 39.0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 39.0, but got %G", [[r dereference] doubleValue]];
    }
    target = [[NSNumber alloc] initWithDouble: 700];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target predicate: greater];
    [target release];
    if ([[r dereference] doubleValue] != 700.0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 700.0, but got %G", [[r dereference] doubleValue]];
    }
    target = [[NSNumber alloc] initWithDouble: 10000.0];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target predicate: greater];
    [target release];
    if (![r isEqual: [l begin]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected to be at the beginning"];
    }
    target = [[NSNumber alloc] initWithDouble: -10000.0];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target predicate: greater];
    [target release];
    if (![r isEqual: [l end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected to be at the end"];
    }
    [greater release];
    [l release];
}

- (void) testMakeHeap
{
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    OLArrayIterator* begin;
    OLArrayIterator* end;
    int i;

    v = [[OLVector alloc] init];
    for (i = 0; i < 10000; i++)
    {
        num = [[NSNumber alloc] initWithInt: lrand48() % 10000];
        [v pushBack: num];
        [num release];
    }
    begin = [v begin];
    end = [v end];
    [OLAlgorithm makeHeapFrom: begin to: end];
    if (![OLAlgorithm isHeapFrom: begin to: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    [OLAlgorithm randomShuffleFrom: begin to: end];
    greater = [[OLGreater alloc] init];
    [OLAlgorithm makeHeapFrom: begin to: end predicate: greater];
    if (![OLAlgorithm isHeapFrom: begin to: end predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    [greater release];
    [v release];
}

- (void) testMerge
{
    OLList* l;
    OLDeque* d;
    OLVector* v;
    OLBackInsertIterator* bii;
    NSNumber* num;
    OLGreater* greater;
    int i;
    int count;
    int next;

    l = [[OLList alloc] init];
    d = [[OLDeque alloc] init];
    for (i = 0; i < 20; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        if (i & 1)
            [l pushBack: num];
        else
            [d pushBack: num];
        [num release];
    }
    v = [[OLVector alloc] init];
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    [OLAlgorithm mergeFrom: [l begin] to: [l end] andFrom: [d begin] andTo: [d end]
        destination: bii];
    for (i = 0; i < 20; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    [l clear];
    [d clear];
    [v clear];
    count = lrand48() % 10000;
    for (i = count; i > 0; i--)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    count = lrand48() % 10000;
    for (i = count; i > 0; i--)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    greater = [[OLGreater alloc] init];
    [OLAlgorithm mergeFrom: [l begin] to: [l end] andFrom: [d begin] andTo: [d end]
        destination: bii predicate: greater];
    [greater release];
    count = [v size];
    for (i = 0, next = 1; next < count; i++, next++)
    {
        if ([[v at: next] intValue] > [[v at: i] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "%i is less than %i",
                [[v at: next] intValue], [[v at: i] intValue]];
        }
    }
    [l release];
    [d release];
    [v release];
    [bii release];
}

- (void) testMinMax
{
    NSNumber* one = [NSNumber numberWithInt: 1];
    NSNumber* two = [NSNumber numberWithInt: 2];
    OLGreater* greater;
    id result;

    result = [OLAlgorithm min: one or: two];
    if ([result intValue] != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %i", [result intValue]];
    }
    if (result != one)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The same id must be returned"];
    }
    result = [OLAlgorithm max: one or: two];
    if ([result intValue] != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %i", [result intValue]];
    }
    if (result != two)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The same id must be returned"];
    }
    greater = [[OLGreater alloc] init];
    result = [OLAlgorithm min: one or: two predicate: greater];
    if ([result intValue] != 2)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 2, but got %i", [result intValue]];
    }
    if (result != two)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The same id must be returned"];
    }
    result = [OLAlgorithm max: one or: two predicate: greater];
    if ([result intValue] != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %i", [result intValue]];
    }
    if (result != one)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The same id must be returned"];
    }
    [greater release];
}

- (void) testMinMaxElement
{
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    OLForwardIterator* r;
    OLArrayIterator* begin;
    OLArrayIterator* end;
    int i;

    v = [[OLVector alloc] init];
    for (i = 0; i < 1000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    begin = [v begin];
    end = [v end];
    [OLAlgorithm randomShuffleFrom: begin to: end];
    r = [OLAlgorithm minElementFrom: begin to: end];
    if ([[r dereference] intValue] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %i", [[r dereference] intValue]];
    }
    [self logMessage: "Found 0 at index %u", [OLIterator distanceFrom: begin to: r]];
    r = [OLAlgorithm maxElementFrom: begin to: end];
    if ([[r dereference] intValue] != 999)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 999, but got %i", [[r dereference] intValue]];
    }
    [self logMessage: "Found 999 at index %u", [OLIterator distanceFrom: begin to: r]];
    greater = [[OLGreater alloc] init];
    [OLAlgorithm randomShuffleFrom: begin to: end];
    r = [OLAlgorithm minElementFrom: begin to: end predicate: greater];
    if ([[r dereference] intValue] != 999)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 999, but got %i", [[r dereference] intValue]];
    }
    [self logMessage: "Found 999 at index %u", [OLIterator distanceFrom: begin to: r]];
    r = [OLAlgorithm maxElementFrom: begin to: end predicate: greater];
    [greater release];
    if ([[r dereference] intValue] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %i", [[r dereference] intValue]];
    }
    [self logMessage: "Found 0 at index %u", [OLIterator distanceFrom: begin to: r]];
    [v release];
}

- (void) testMismatch
{
    OLVector* v;
    OLDeque* d;
    OLPair* p;
    NSNumber* num;
    OLGreaterEqual* ge;
    int i;

    v = [[OLVector alloc] init];
    d = [[OLDeque alloc] init];
    for (i = 0; i < 20; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [d pushBack: num];
        [num release];
        if (i == 13)
        {
            num = [[NSNumber alloc] initWithInt: i];
            [d pushBack: num];
            [num release];
        }
    }
    p = [OLAlgorithm mismatchFrom: [v begin] to: [v end] with: [d begin]];
    if ([[[p first] dereference] intValue] != 14)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 14, but got %i", [[[p first] dereference] intValue]];
    }
    if ([[[p second] dereference] intValue] != 13)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 13, but got %i", [[[p second] dereference] intValue]];
    }
    ge = [[OLGreaterEqual alloc] init];
    p = [OLAlgorithm mismatchFrom: [d begin] to: [d end] with: [v begin] predicate: ge];
    [ge release];
    if ([[[p first] dereference] intValue] != 13)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 13, but got %i", [[[p first] dereference] intValue]];
    }
    if ([[[p second] dereference] intValue] != 14)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 14, but got %i", [[[p second] dereference] intValue]];
    }
    [v release];
    [d release];
}

- (void) testNextPermutation
{
    OLVector* v;
    NSNumber* num;
    OLArrayIterator* begin;
    OLArrayIterator* end;
    NSMutableSet* set;
    NSArray* array;
    OLGreater* greater;
    typedef struct { int one; int two; int three; } Perm;
    Perm perms[] =
    {
        { 1, 2, 3 },
        { 1, 3, 2 },
        { 2, 1, 3 },
        { 2, 3, 1 },
        { 3, 1, 2 },
        { 3, 2, 1 }
    };
    id objs[5];
    int i;
    int j;
    int val;

    v = [[OLVector alloc] init];
    for (i = 1; i < 4; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    begin = [v begin];
    end = [v end];
    for (i = 0; i < 6; i++)
    {
        [self logMessage: "[%i] %i %i %i",
            i, [[v at: 0] intValue], [[v at: 1] intValue], [[v at: 2] intValue]];
        for (j = 0; j < 3; j++)
        {
            val = *((int*)(((int*)&perms[i])) + j);
            if ([[v at: j] intValue] != val)
            {
                [self errInFile: __FILE__ line: __LINE__
                    format: "Expected %i, but got %i",
                    val, [[v at: j] intValue]];
            }
        }
        if (![OLAlgorithm nextPermutationFrom: begin to: end] && i < 5)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected a successful run"];
        }
    }
    [v clear];
    for (i = 4; i >= 0; i--)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    set = [[NSMutableSet alloc] init];
    j = 0;
    greater = [[OLGreater alloc] init];
    begin = [v begin];
    end = [v end];
    do
    {
        for (i = 0; i < 5; i++)
            objs[i] = [v at: i];
        array = [[NSArray alloc] initWithObjects: objs count: 5];
        if ([set containsObject: array])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The array \"%s\" was already found",
                [[array description] cString]];
        }
        [set addObject: array];
        [array release];
        j++;
    } while ([OLAlgorithm nextPermutationFrom: begin to: end predicate: greater]);
    [self logMessage: "Found %i permutations", j];
    [set release];
    [greater release];
    [v release];
}

- (void) testNthElement
{
    OLVector* v;
    NSNumber* num;
    OLArrayIterator* mid;
    OLArrayIterator* itor;
    OLArrayIterator* end;
    OLGreater* greater;
    int nums[] = { 4, 10, 70, 30, 10, 69, 96, 100 };
    int i;
    int pivot;

    v = [[OLVector alloc] init];
    for (i = 0; i < 8; i++)
    {
        num = [[NSNumber alloc] initWithInt: nums[i]];
        [v pushBack: num];
        [num release];
    }
    mid = [[v begin] advanceBy: 4];
    [OLAlgorithm nthElementFrom: [v begin] nth: mid to: [v end]];
    mid = [[v begin] advanceBy: 2];
    if ([[mid dereference] intValue] != 10)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10, but got %i", [[mid dereference] intValue]];
    }
    itor = [mid copy];
    [itor reverse];
    i = [[itor dereference] intValue];
    if (i != 10 && i != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10 or 4, but got %i", [[itor dereference] intValue]];
    }
    [itor reverse];
    if (i != 10 && i != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10 or 4, but got %i", [[itor dereference] intValue]];
    }
    [itor release];
    [mid advance];
    end = [v end];
    for ( ; ![mid isEqual: end]; [mid advance])
    {
        if ([[mid dereference] intValue] <= 10)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The value %i is greater than 10", [[mid dereference] intValue]];
        }
    }
    [v clear];
    for (i = 0; i < 10000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    [OLAlgorithm randomShuffleFrom: [v begin] to: [v end]];
    mid = [[v begin] advanceBy: 5027];
    greater = [[OLGreater alloc] init];
    [OLAlgorithm nthElementFrom: [v begin] nth: mid to: [v end] predicate: greater];
    [mid reverse];
    pivot = [[mid dereference] intValue];
    [mid advance];
    [greater release];
    for (itor = [v begin]; ![itor isEqual: mid]; [itor advance])
    {
        if ([[itor dereference] intValue] < pivot)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The value %i is less than %i",
                [[itor dereference] intValue], pivot];
        }
    }
    end = [v end];
    for ([itor advance]; ![itor isEqual: end]; [itor advance])
    {
        if ([[itor dereference] intValue] >= pivot)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The value %i is not less than %i",
                [[itor dereference] intValue], pivot];
        }
    }
    [v release];
}

- (void) testPartialSort
{
    OLDeque* d;
    NSNumber* num;
    OLDequeIterator* mid;
    OLGreater* greater;
    int i;
    int j;
    int pivot;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 10; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end]];
    [self logMessage: "Pre partial sort: %i %i %i %i %i %i %i %i %i %i",
       [[d at: 0] intValue], [[d at: 1] intValue], [[d at: 2] intValue], [[d at: 3] intValue],
       [[d at: 4] intValue], [[d at: 5] intValue], [[d at: 6] intValue], [[d at: 7] intValue],
       [[d at: 8] intValue], [[d at: 9] intValue]];
    mid = [[d begin] advanceBy: 3];
    [OLAlgorithm partialSortFrom: [d begin] middle: mid to: [d end]];
    [self logMessage: "Post partial sort: %i %i %i %i %i %i %i %i %i %i",
       [[d at: 0] intValue], [[d at: 1] intValue], [[d at: 2] intValue], [[d at: 3] intValue],
       [[d at: 4] intValue], [[d at: 5] intValue], [[d at: 6] intValue], [[d at: 7] intValue],
       [[d at: 8] intValue], [[d at: 9] intValue]];
    for (i = 0; i < 3; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The number %i at position %i should be %i",
                [[d at: i] intValue], i, i];
        }
    }
    pivot = [[[mid reverse] dereference] intValue];
    for ( ; i < 10; i++)
    {
        if ([[d at: i] intValue] < pivot)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The number %i at position %i is not less than %i",
                [[d at: i] intValue], i, pivot];
        }
    }
    [d clear];
    for (i = 0; i < 50000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end]];
    mid = [[d begin] advanceBy: 4528];
    greater = [[OLGreater alloc] init];
    [OLAlgorithm partialSortFrom: [d begin] middle: mid to: [d end] predicate: greater];
    [greater release];
    for (i = 0, j = 49999; i < 4528; i++, j--)
    {
        if ([[d at: i] intValue] != j)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The number %i at position %i should be %i",
                [[d at: i] intValue], i, j];
        }
    }
    pivot = [[[mid reverse] dereference] intValue];
    for ( ; i < 50000; i++)
    {
        if ([[d at: i] intValue] > pivot)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The number %i at position %i is not less than %i",
                [[d at: i] intValue], i, pivot];
        }
    }
    [d release];
}

- (void) testPartialSortCopy
{
    OLDeque* d;
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    int i;
    int j;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 10; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end]];
    v = [[OLVector alloc] initWithSize: 5 filledWith: @"junk"];
    [OLAlgorithm partialSortCopyFrom: [d begin] to: [d end]
        destinationFrom: [v begin] destinationTo: [v end]];
    for (i = 0; i < 5; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    [v clear];
    [v assign: 20 filledWith: @"junk"];
    [OLAlgorithm partialSortCopyFrom: [d begin] to: [d end]
        destinationFrom: [v begin] destinationTo: [v end]];
    for (i = 0; i < 10; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    for (; i < 20; i++)
    {
        if (![[v at: i] isEqual: @"junk"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Item %i should be junk", i];
        }
    }
    [d clear];
    for (i = 0; i < 75000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end]];
    greater = [[OLGreater alloc] init];
    [OLAlgorithm partialSortCopyFrom: [d begin] to: [d end]
        destinationFrom: [v begin] destinationTo: [v end] predicate: greater];
    for (i = 0, j = 74999; i < 20; i++, j--)
    {
        if ([[v at: i] intValue] != j)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                j, [[v at: i] intValue]];
        }
    }
    [v clear];
    [v assign: 100000 filledWith: @"junk"];
    [OLAlgorithm partialSortCopyFrom: [d begin] to: [d end]
        destinationFrom: [v begin] destinationTo: [v end] predicate: greater];
    for (i = 0, j = 74999; i < 75000; i++, j--)
    {
        if ([[v at: i] intValue] != j)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                j, [[v at: i] intValue]];
        }
    }
    for ( ; i < 100000; i++)
    {
        if (![[v at: i] isEqual: @"junk"])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Item %i should be junk", i];
        }
    }
    [greater release];
    [v release];
    [d release];
}

- (void) testPartition
{
    OLDeque* d;
    NSNumber* num;
    OLBidirectionalIterator* r;
    PartitionFunction* func;
    OLDequeIterator* itor;
    OLDequeIterator* end;
    int i;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 1000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    itor = [d begin];
    end = [d end];
    [OLAlgorithm randomShuffleFrom: itor to: end];
    func = [[PartitionFunction alloc] initWithValue: 673];
    r = [OLAlgorithm partitionFrom: itor to: end predicate: func];
    for ( ; ![itor isEqual: r]; [itor advance])
    {
        if (![func performUnaryFunctionWithArg: [itor dereference]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i to be less than 673", [[itor dereference] intValue]];
        }
    }
    for ( ; ![itor isEqual: end]; [itor advance])
    {
        if ([func performUnaryFunctionWithArg: [itor dereference]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i to be not less than 673", [[itor dereference] intValue]];
        }
    }
    [func release];
    [d release];
}

- (void) testPopHeap
{
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    OLArrayIterator* begin;
    OLArrayIterator* end;
    int i;

    v = [[OLVector alloc] init];
    for (i = 0; i < 10000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    begin = [v begin];
    end = [v end];
    [OLAlgorithm makeHeapFrom: begin to: end];
    if (![OLAlgorithm isHeapFrom: begin to: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    [OLAlgorithm popHeapFrom: begin to: end];
    [end reverse];
    if (![OLAlgorithm isHeapFrom: begin to: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    if ([[end dereference] intValue] != 9999)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 9999, but got %i", [[end dereference] intValue]];
    }
    [end advance];
    greater = [[OLGreater alloc] init];
    [OLAlgorithm makeHeapFrom: begin to: end predicate: greater];
    if (![OLAlgorithm isHeapFrom: begin to: end predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    [OLAlgorithm popHeapFrom: begin to: end predicate: greater];
    [end reverse];
    if (![OLAlgorithm isHeapFrom: begin to: end predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    if ([[end dereference] intValue] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %i", [[end dereference] intValue]];
    }
    [greater release];
    [v release];
}

- (void) testPrevPermutation
{
    OLVector* v;
    NSNumber* num;
    OLArrayIterator* begin;
    OLArrayIterator* end;
    NSMutableSet* set;
    NSArray* array;
    OLGreater* greater;
    typedef struct { int one; int two; int three; } Perm;
    Perm perms[] =
    {
        { 3, 2, 1 },
        { 3, 1, 2 },
        { 2, 3, 1 },
        { 2, 1, 3 },
        { 1, 3, 2 },
        { 1, 2, 3 }
    };
    id objs[5];
    int i;
    int j;
    int val;

    v = [[OLVector alloc] init];
    for (i = 3; i >= 1; i--)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    begin = [v begin];
    end = [v end];
    for (i = 0; i < 6; i++)
    {
        [self logMessage: "[%i] %i %i %i",
            i, [[v at: 0] intValue], [[v at: 1] intValue], [[v at: 2] intValue]];
        for (j = 0; j < 3; j++)
        {
            val = *((int*)(((int*)&perms[i])) + j);
            if ([[v at: j] intValue] != val)
            {
                [self errInFile: __FILE__ line: __LINE__
                    format: "Expected %i, but got %i",
                    val, [[v at: j] intValue]];
            }
        }
        if (![OLAlgorithm prevPermutationFrom: begin to: end] && i < 5)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected a successful run"];
        }
    }
    [v clear];
    for (i = 0; i < 5; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    set = [[NSMutableSet alloc] init];
    j = 0;
    greater = [[OLGreater alloc] init];
    begin = [v begin];
    end = [v end];
    do
    {
        for (i = 0; i < 5; i++)
            objs[i] = [v at: i];
        array = [[NSArray alloc] initWithObjects: objs count: 5];
        if ([set containsObject: array])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The array \"%s\" was already found",
                [[array description] cString]];
        }
        [set addObject: array];
        [array release];
        j++;
    } while ([OLAlgorithm prevPermutationFrom: begin to: end predicate: greater]);
    [self logMessage: "Found %i permutations", j];
    [set release];
    [greater release];
    [v release];
}

- (void) testPushHeap
{
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    OLArrayIterator* begin;
    OLArrayIterator* end;
    int i;

    v = [[OLVector alloc] init];
    for (i = 0; i < 10000; i++)
    {
        num = [[NSNumber alloc] initWithInt: lrand48() % 10000];
        [v pushBack: num];
        [num release];
    }
    begin = [v begin];
    end = [v end];
    [OLAlgorithm makeHeapFrom: begin to: end];
    if (![OLAlgorithm isHeapFrom: begin to: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    num = [[NSNumber alloc] initWithInt: lrand48() % 10000];
    [v pushBack: num];
    [num release];
    begin = [v begin];
    end = [v end];
    [OLAlgorithm pushHeapFrom: begin to: end];
    if (![OLAlgorithm isHeapFrom: begin to: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    greater = [[OLGreater alloc] init];
    [OLAlgorithm makeHeapFrom: begin to: end predicate: greater];
    if (![OLAlgorithm isHeapFrom: begin to: end predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    num = [[NSNumber alloc] initWithInt: lrand48() % 10000];
    [v pushBack: num];
    [num release];
    begin = [v begin];
    end = [v end];
    if ([OLAlgorithm isHeapFrom: begin to: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It shouldn't be a heap"];
    }
    [OLAlgorithm pushHeapFrom: begin to: end predicate: greater];
    if (![OLAlgorithm isHeapFrom: begin to: end predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    [greater release];
    [v release];
}

- (void) testRandomShuffle
{
    OLDeque* d;
    OLDeque* d1;
    NSNumber* num;
    RandomGen* gen;
    int i;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 10; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    d1 = [[OLDeque alloc] initWithDeque: d];
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end]];
    if ([d isEqual: d1])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should not be equal"];
    }
    [self logMessage: "First random shuffle: %i %i %i %i %i %i %i %i %i %i",
       [[d at: 0] intValue], [[d at: 1] intValue], [[d at: 2] intValue], [[d at: 3] intValue],
       [[d at: 4] intValue], [[d at: 5] intValue], [[d at: 6] intValue], [[d at: 7] intValue],
       [[d at: 8] intValue], [[d at: 9] intValue]];
    [d1 assignFrom: [d begin] to: [d end]];
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end]];
    if ([d isEqual: d1])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should not be equal"];
    }
    [self logMessage: "Second random shuffle: %i %i %i %i %i %i %i %i %i %i",
       [[d at: 0] intValue], [[d at: 1] intValue], [[d at: 2] intValue], [[d at: 3] intValue],
       [[d at: 4] intValue], [[d at: 5] intValue], [[d at: 6] intValue], [[d at: 7] intValue],
       [[d at: 8] intValue], [[d at: 9] intValue]];
    [d1 assignFrom: [d begin] to: [d end]];
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end]];
    if ([d isEqual: d1])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should not be equal"];
    }
    [self logMessage: "Third random shuffle: %i %i %i %i %i %i %i %i %i %i",
       [[d at: 0] intValue], [[d at: 1] intValue], [[d at: 2] intValue], [[d at: 3] intValue],
       [[d at: 4] intValue], [[d at: 5] intValue], [[d at: 6] intValue], [[d at: 7] intValue],
       [[d at: 8] intValue], [[d at: 9] intValue]];
    [d1 assignFrom: [d begin] to: [d end]];
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end]];
    if ([d isEqual: d1])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should not be equal"];
    }
    [self logMessage: "Fourth random shuffle: %i %i %i %i %i %i %i %i %i %i",
       [[d at: 0] intValue], [[d at: 1] intValue], [[d at: 2] intValue], [[d at: 3] intValue],
       [[d at: 4] intValue], [[d at: 5] intValue], [[d at: 6] intValue], [[d at: 7] intValue],
       [[d at: 8] intValue], [[d at: 9] intValue]];
    gen = [[RandomGen alloc] init];
    [d clear];
    for (i = 0; i < 10000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    [d1 assignFrom: [d begin] to: [d end]];
    [OLAlgorithm randomShuffleFrom: [d begin] to: [d end] randGen: gen];
    [gen release];
    if ([d isEqual: d1])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequences should not be equal"];
    }
    [d release];
    [d1 release];
}

- (void) testRemove
{
    OLList* l;
    NSNumber* num;
    LessThanFive* func;
    OLForwardIterator* r;
    OLListIterator* begin;
    OLListIterator* end;
    int i;

    l = [[OLList alloc] init];
    for (i = 0; i < 10; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    num = [[NSNumber alloc] initWithInt: 5];
    begin = [l begin];
    end = [l end];
    r = [OLAlgorithm removeFrom: begin to: end value: num];
    if ([OLIterator distanceFrom: begin to: r] != 9)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 9, but got %i",
            [OLIterator distanceFrom: begin to: r]];
    }
    if ([OLIterator distanceFrom: r to: end] != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %i",
            [OLIterator distanceFrom: r to: end]];
    }
    if ([OLAlgorithm binarySearchFrom: begin to: r value: num])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number should not have been found"];
    }
    [num release];
    func = [[LessThanFive alloc] init];
    [l eraseFrom: (OLListIterator*)r to: end];
    end = [l end];
    r = [OLAlgorithm removeFrom: begin to: end if: func];
    [func release];
    if ([OLIterator distanceFrom: begin to: r] != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %i",
            [OLIterator distanceFrom: begin to: r]];
    }
    if ([OLIterator distanceFrom: r to: end] != 5)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 5, but got %i",
            [OLIterator distanceFrom: r to: end]];
    }
    [l eraseFrom: (OLListIterator*)r to: end];
    end = [l end];
    for ( ; ![begin isEqual: end]; [begin advance])
    {
        if ([[begin dereference] intValue] < 5)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "%i is less than 5", [[begin dereference] intValue]];
        }
    }
    [l release];
}

- (void) testRemoveCopy
{
    OLDeque* d;
    OLVector* v;
    NSNumber* num;
    OLBackInsertIterator* bii;
    LessThanFive* func;
    int i;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 10; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    v = [[OLVector alloc] init];
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    num = [[NSNumber alloc] initWithInt: 5];
    [OLAlgorithm removeCopyFrom: [d begin] to: [d end] destination: bii value: num];
    if ([v size] != 9)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 9, but got %i", [v size]];
    }
    if ([OLAlgorithm binarySearchFrom: [v begin] to: [v end] value: num])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The number should not have been found"];
    }
    [num release];
    func = [[LessThanFive alloc] init];
    [v clear];
    [OLAlgorithm removeCopyFrom: [d begin] to: [d end] destination: bii if: func];
    [func release];
    for (i = 0; i < [v size]; i++)
    {
        if ([[v at: i] intValue] < 5)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "%i is less than 5", [[v at: i] intValue]];
        }
    }
    [v release];
    [d release];
    [bii release];
}

- (void) testReplace
{
    OLDeque* d;
    NSNumber* num;
    NSNumber* num2;
    LessThanFive* func;
    int i;
    unsigned count;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 20; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    num = [[NSNumber alloc] initWithInt: 13];
    num2 = [[NSNumber alloc] initWithInt: 7527];
    [OLAlgorithm replaceFrom: [d begin] to: [d end]
        oldValue: num newValue: num2];
    [num release];
    if ([[d at: 13] intValue] != 7527)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 7527, but got %i", [[d at: 13] intValue]];
    }
    count = [OLAlgorithm countFrom: [d begin] to: [d end] value: num2];
    if (count != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %i", count];
    }
    func = [[LessThanFive alloc] init];
    [OLAlgorithm replaceFrom: [d begin] to: [d end]
        if: func newValue: num2];
    [func release];
    [num2 release];
    for (i = 0; i < 5; i++)
    {
        if ([[d at: i] intValue] != 7527)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected 7527, but got %i", [[d at: i] intValue]];
        }
    }
    for ( ; i < 13; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[d at: i] intValue]];
        }
    }
    if ([[d at: i] intValue] != 7527)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 7527, but got %i", [[d at: i] intValue]];
    }
    for (i++ ; i < 20; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[d at: i] intValue]];
        }
    }
    [d release];
}

- (void) testReplaceCopy
{
    OLDeque* d;
    OLVector* v;
    NSNumber* num;
    NSNumber* num2;
    OLBackInsertIterator* bii;
    LessThanFive* func;
    int i;
    unsigned count;

    d = [[OLDeque alloc] init];
    v = [[OLVector alloc] init];
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    for (i = 0; i < 20; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    num = [[NSNumber alloc] initWithInt: 13];
    num2 = [[NSNumber alloc] initWithInt: 7527];
    [OLAlgorithm replaceCopyFrom: [d begin] to: [d end] destination: bii
        oldValue: num newValue: num2];
    [num release];
    if ([v size] != [d size])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %u, but got %u", [d size], [v size]];
    }
    if ([[v at: 13] intValue] != 7527)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 7527, but got %i", [[v at: 13] intValue]];
    }
    if ([[d at: 13] intValue] != 13)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 13, but got %i", [[d at: 13] intValue]];
    }
    count = [OLAlgorithm countFrom: [v begin] to: [v end] value: num2];
    if (count != 1)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 1, but got %i", count];
    }
    [v clear];
    func = [[LessThanFive alloc] init];
    [OLAlgorithm replaceCopyFrom: [d begin] to: [d end] destination: bii
        if: func newValue: num2];
    [func release];
    [num2 release];
    if ([v size] != [d size])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %u, but got %u", [d size], [v size]];
    }
    for (i = 0; i < 5; i++)
    {
        if ([[v at: i] intValue] != 7527)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected 7527, but got %i", [[v at: i] intValue]];
        }
    }
    for ( ; i < 20; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[v at: i] intValue]];
        }
    }
    for (i = 0; i < 20; i++)
    {
        if ([[d at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[d at: i] intValue]];
        }
    }
    [d release];
    [v release];
    [bii release];
}

- (void) testReverse
{
    OLVector* v;
    NSNumber* num;
    int i;

    v = [[OLVector alloc] init];
    for (i = 0; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    [OLAlgorithm reverseFrom: [v begin] to: [v end]];
    for (i = 0; i < 100; i++)
    {
        if ([[v at: i] intValue] != 99 - i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got, %i",
                99 - i, [[v at: i] intValue]];
        }
    }
    [v release];
}

- (void) testReverseCopy
{
    OLVector* v;
    OLList* l;
    NSNumber* num;
    OLBackInsertIterator* bii;
    OLReverseBidiIterator* litor;
    OLReverseBidiIterator* lend;
    OLArrayIterator* vitor;
    OLArrayIterator* vend;
    int i;

    l = [[OLList alloc] init];
    v = [[OLVector alloc] init];
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    for (i = 0; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    [OLAlgorithm reverseCopyFrom: [l begin] to: [l end] destination: bii];
    if ([v size] != [l size])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected %u, but got, %u", [l size], [v size]];
    }
    for (litor = [l rbegin], lend = [l rend], vitor = [v begin], vend = [v end];
         ![vitor isEqual: vend];
         [vitor advance], [litor advance])
    {
        if ([[vitor dereference] intValue] != [[litor dereference] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got, %i",
                [[litor dereference] intValue], [[vitor dereference] intValue]];
        }
    }
    [l release];
    [v release];
    [bii release];
}

- (void) testRotate
{
    OLList* l;
    NSString* strs[] = { @"one", @"two", @"three" };
    OLForwardIterator* r;
    OLListIterator* itor;
    OLListIterator* mid;
    OLListIterator* end;
    OLVector* v;
    OLArrayIterator* vtor;
    OLArrayIterator* vend;
    NSNumber* num;
    int i;

    l = [[OLList alloc] init];
    [l pushBack: strs[0]];
    [l pushBack: strs[1]];
    [l pushBack: strs[2]];
    r = [OLAlgorithm rotateFrom: [l begin] middle: [[l begin] advance] to: [l end]];
    if (![[r dereference] isEqual: strs[0]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"one\", but got \"%s\"", [[r dereference] cString]];
    }
    if (![[l front] isEqual: strs[1]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"two\", but got \"%s\"", [[l front] cString]];
    }
    itor = [[l begin] advance];
    if (![[itor dereference] isEqual: strs[2]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"three\", but got \"%s\"", [[itor dereference] cString]];
    }
    if (![[l back] isEqual: strs[0]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"one\", but got \"%s\"", [[l back] cString]];
    }
    [l clear];
    for (i = 0; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    mid = [l begin];
    [OLIterator advanceIterator: mid distance: 51];
    r = [OLAlgorithm rotateFrom: [l begin] middle: mid to: [l end]];
    if ([[r dereference] intValue] != 0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 0, but got %i", [[r dereference] intValue]];
    }
    for (itor = [l begin], i = 51; ![itor isEqual: r]; [itor advance], i++)
    {
        if ([[itor dereference] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[itor dereference] intValue]];
        }
    }
    end = [l end];
    for (i = 0; ![r isEqual: end]; [r advance], i++)
    {
        if ([[r dereference] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[r dereference] intValue]];
        }
    }
    [l sort];
    v = [[OLVector alloc] initWithSize: [l size] filledWith: @"yo"];
    mid = [l begin];
    [OLIterator advanceIterator: mid distance: 37];
    r = [OLAlgorithm rotateCopyFrom: [l begin] middle: mid to: [l end] destination: [v begin]];
    [l release];
    vend = [v end];
    if (![r isEqual: vend])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The iterator must be at the end of the sequence"];
    }
    for (vtor = [v begin], i = 37; i < 100; [vtor advance], i++)
    {
        if ([[vtor dereference] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[vtor dereference] intValue]];
        }
    }
    for (i = 0; i < 37; [vtor advance], i++)
    {
        if ([[vtor dereference] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[vtor dereference] intValue]];
        }
    }
    [v release];
}

- (void) testSearch
{
    OLDeque* d;
    OLVector* v;
    NSNumber* num;
    OLForwardIterator* r;
    IntCompare* comp;
    OLDequeIterator* dbegin;
    OLDequeIterator* dend;
    int i;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 1000; i++)
    {
        num = [[NSNumber alloc] initWithDouble: i + .5];
        [d pushBack: num];
        [num release];
    }
    v = [[OLVector alloc] init];
    for (i = 784; i < 899; i++)
    {
        num = [[NSNumber alloc] initWithDouble: i + 0.5];
        [v pushBack: num];
        [d pushBack: num];
        [num release];
    }
    dbegin = [d begin];
    dend = [d end];
    r = [OLAlgorithm searchFrom: dbegin to: dend subFrom: [v begin] subTo: [v end]];
    if ([r isEqual: dend])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should have been found"];
    }
    if ([[r dereference] doubleValue] != 784.5)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 784, but got %i", [[r dereference] intValue]];
    }
    if ([OLIterator distanceFrom: dbegin to: r] != 784)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Search found the last one, not the first one (distance %u)",
            [OLIterator distanceFrom: dbegin to: r]];
    }
    [v clear];
    for (i = 784; i < 899; i++)
    {
        num = [[NSNumber alloc] initWithDouble: i];
        [v pushBack: num];
        [num release];
    }
    comp = [[IntCompare alloc] init];
    r = [OLAlgorithm searchFrom: dbegin to: dend subFrom: [v begin] subTo: [v end]
        predicate: comp];
    [comp release];
    if ([r isEqual: dend])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The value should have been found"];
    }
    if ([[r dereference] doubleValue] != 784.5)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 784, but got %i", [[r dereference] intValue]];
    }
    if ([OLIterator distanceFrom: dbegin to: r] != 784)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Search found the last one, not the first one"];
    }
    [d release];
    [v release];
}

- (void) testSearchCount
{
    OLVector* v;
    NSNumber* num;
    OLForwardIterator* r;
    OLArrayIterator* begin;
    OLArrayIterator* end;
    IntCompare* comp;
    int nums[] = { 1, 2, 2, 7, 2, 2, 2, 4, 9, 6 };
    int i;

    v = [[OLVector alloc] init];
    for (i = 0; i < 10; i++)
    {
        num = [[NSNumber alloc] initWithDouble: nums[i] + 0.3];
        [v pushBack: num];
        [num release];
    }
    num = [[NSNumber alloc] initWithDouble: 2.3];
    begin = [v begin];
    end = [v end];
    r = [OLAlgorithm searchFrom: begin to: end count: 3 value: num];
    [num release];
    if ([r isEqual: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequence should have been found"];
    }
    if ([OLIterator distanceFrom: begin to: r] != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %u",
            [OLIterator distanceFrom: begin to: r]];
    }
    comp = [[IntCompare alloc] init];
    num = [[NSNumber alloc] initWithInt: 2];
    r = [OLAlgorithm searchFrom: begin to: end count: 3 value: num predicate: comp];
    [num release];
    [comp release];
    if ([r isEqual: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The sequence should have been found"];
    }
    if ([OLIterator distanceFrom: begin to: r] != 4)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 4, but got %u",
            [OLIterator distanceFrom: begin to: r]];
    }
    [v release];
}

- (void) testSetDifference
{
    OLDeque* d;
    OLList* l;
    OLVector* v;
    NSNumber* num;
    OLBackInsertIterator* bii;
    OLGreater* greater;
    int i;

    d = [[OLDeque alloc] init];
    l = [[OLList alloc] init];
    v = [[OLVector alloc] init];
    for (i = 0; i < 50; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    for ( ; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [d pushBack: num];
        [num release];
    }
    for ( ; i < 150; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    [OLAlgorithm setDifferenceFrom: [l begin] to: [l end]
        andFrom: [d begin] andTo: [d end] destination: bii];
    if ([v size] != 50)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 50, but got %i", [v size]];
    }
    for (i = 0; i < 50; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    [v clear];
    greater = [[OLGreater alloc] init];
    [l sortWith: greater];
    [OLAlgorithm sortFrom: [d begin] to: [d end] predicate: greater];
    [OLAlgorithm setDifferenceFrom: [l begin] to: [l end]
        andFrom: [d begin] andTo: [d end] destination: bii predicate: greater];
    [greater release];
    if ([v size] != 50)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 50, but got %i", [v size]];
    }
    for (i = 0; i < 50; i++)
    {
        if ([[v at: i] intValue] != 49 - i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                49 - i, [[v at: i] intValue]];
        }
    }
    [v release];
    [l release];
    [d release];
    [bii release];
}

- (void) testSetIntersection
{
    OLDeque* d;
    OLList* l;
    OLVector* v;
    NSNumber* num;
    OLBackInsertIterator* bii;
    OLGreater* greater;
    int i;

    d = [[OLDeque alloc] init];
    l = [[OLList alloc] init];
    v = [[OLVector alloc] init];
    for (i = 0; i < 50; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    for ( ; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [d pushBack: num];
        [num release];
    }
    for ( ; i < 150; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    [OLAlgorithm setIntersectionFrom: [l begin] to: [l end]
        andFrom: [d begin] andTo: [d end] destination: bii];
    if ([v size] != 50)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 50, but got %i", [v size]];
    }
    for (i = 50; i < 100; i++)
    {
        if ([[v at: i - 50] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i - 50] intValue]];
        }
    }
    [v clear];
    greater = [[OLGreater alloc] init];
    [l sortWith: greater];
    [OLAlgorithm sortFrom: [d begin] to: [d end] predicate: greater];
    [OLAlgorithm setIntersectionFrom: [l begin] to: [l end]
        andFrom: [d begin] andTo: [d end] destination: bii predicate: greater];
    [greater release];
    if ([v size] != 50)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 50, but got %i", [v size]];
    }
    for (i = 0; i < 50; i++)
    {
        if ([[v at: i] intValue] != 99 - i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                99 - i, [[v at: i] intValue]];
        }
    }
    [v release];
    [l release];
    [d release];
    [bii release];
}

- (void) testSetSymmetricDifference
{
    OLDeque* d;
    OLList* l;
    OLVector* v;
    NSNumber* num;
    OLBackInsertIterator* bii;
    OLGreater* greater;
    int i;

    d = [[OLDeque alloc] init];
    l = [[OLList alloc] init];
    v = [[OLVector alloc] init];
    for (i = 0; i < 50; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    for ( ; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [d pushBack: num];
        [num release];
    }
    for ( ; i < 150; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    [OLAlgorithm setSymmetricDifferenceFrom: [l begin] to: [l end]
        andFrom: [d begin] andTo: [d end] destination: bii];
    if ([v size] != 100)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 100, but got %i", [v size]];
    }
    for (i = 0; i < 50; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    for (i = 100; i < 150; i++)
    {
        if ([[v at: i - 50] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i - 50] intValue]];
        }
    }
    [v clear];
    greater = [[OLGreater alloc] init];
    [l sortWith: greater];
    [OLAlgorithm sortFrom: [d begin] to: [d end] predicate: greater];
    [OLAlgorithm setSymmetricDifferenceFrom: [l begin] to: [l end]
        andFrom: [d begin] andTo: [d end] destination: bii predicate: greater];
    [greater release];
    if ([v size] != 100)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 50, but got %i", [v size]];
    }
    for (i = 0; i < 50; i++)
    {
        if ([[v at: i] intValue] != 149 - i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                149 - i, [[v at: i] intValue]];
        }
    }
    for ( ; i < 100; i++)
    {
        if ([[v at: i] intValue] != 49 - (i - 50))
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                49 - (i - 50), [[v at: i] intValue]];
        }
    }
    [v release];
    [l release];
    [d release];
    [bii release];
}

- (void) testSetUnion
{
    OLDeque* d;
    OLList* l;
    OLVector* v;
    NSNumber* num;
    OLBackInsertIterator* bii;
    OLGreater* greater;
    int i;

    d = [[OLDeque alloc] init];
    l = [[OLList alloc] init];
    v = [[OLVector alloc] init];
    for (i = 0; i < 50; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    for ( ; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [d pushBack: num];
        [num release];
    }
    for ( ; i < 150; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [d pushBack: num];
        [num release];
    }
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    [OLAlgorithm setUnionFrom: [l begin] to: [l end]
        andFrom: [d begin] andTo: [d end] destination: bii];
    if ([v size] != 150)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 150, but got %i", [v size]];
    }
    for (i = 0; i < 150; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    [v clear];
    greater = [[OLGreater alloc] init];
    [l sortWith: greater];
    [OLAlgorithm sortFrom: [d begin] to: [d end] predicate: greater];
    [OLAlgorithm setUnionFrom: [l begin] to: [l end]
        andFrom: [d begin] andTo: [d end] destination: bii predicate: greater];
    [greater release];
    if ([v size] != 150)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 50, but got %i", [v size]];
    }
    for (i = 0; i < 150; i++)
    {
        if ([[v at: i] intValue] != 149 - i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                149 - i, [[v at: i] intValue]];
        }
    }
    [v release];
    [l release];
    [d release];
    [bii release];
}

- (void) testSort
{
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    int i;
    int next;

    v = [[OLVector alloc] init];
    for (i = 0; i < 1000; i++)
    {
        num = [[NSNumber alloc] initWithInt: lrand48() % 1000];
        [v pushBack: num];
        [num release];
    }
    [OLAlgorithm sortFrom: [v begin] to: [v end]];
    for (i = 0, next = 1; next < 1000; i++, next++)
    {
        if ([[v at: next] intValue] < [[v at: i] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The sequence is not sorted"];
        }
    }
    greater = [[OLGreater alloc] init];
    [OLAlgorithm sortFrom: [v begin] to: [v end] predicate: greater];
    [greater release];
    for (i = 0, next = 1; next < 1000; i++, next++)
    {
        if ([[v at: next] intValue] > [[v at: i] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "The sequence is not sorted"];
        }
    }
    [v release];
}

- (void) testSortHeap
{
    OLVector* v;
    NSNumber* num;
    OLGreater* greater;
    OLArrayIterator* begin;
    OLArrayIterator* end;
    int i;

    v = [[OLVector alloc] init];
    for (i = 0; i < 50000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    begin = [v begin];
    end = [v end];
    [OLAlgorithm makeHeapFrom: begin to: end];
    if (![OLAlgorithm isHeapFrom: begin to: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    [OLAlgorithm sortHeapFrom: begin to: end];
    if (![OLAlgorithm isSortedFrom: begin to: end])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not sorted"];
    }
    greater = [[OLGreater alloc] init];
    [OLAlgorithm makeHeapFrom: begin to: end predicate: greater];
    if (![OLAlgorithm isHeapFrom: begin to: end predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not a heap"];
    }
    [OLAlgorithm sortHeapFrom: begin to: end predicate: greater];
    if (![OLAlgorithm isSortedFrom: begin to: end predicate: greater])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "It's not sorted"];
    }
    [greater release];
    [v release];
}

- (void) testStablePartition
{
    OLVector* v;
    OLVector* v2;
    NSNumber* num;
    OLArrayIterator* itor;
    OLArrayIterator* end;
    OLForwardIterator* r;
    PartitionFunction* func;
    OLArrayIterator* itor2;
    int i;

    v = [[OLVector alloc] init];
    for (i = 0; i < 10000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    itor = [v begin];
    end = [v end];
    [OLAlgorithm randomShuffleFrom: itor to: end];
    v2 = [[OLVector alloc] initWithVector: v];
    func = [[PartitionFunction alloc] initWithValue: 4723];
    r = [OLAlgorithm stablePartitionFrom: itor to: end predicate: func];
    for ( ; ![itor isEqual: r]; [itor advance])
    {
        if (![func performUnaryFunctionWithArg: [itor dereference]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i to be less than 4723", [[itor dereference] intValue]];
        }
    }
    for ( ; ![itor isEqual: end]; [itor advance])
    {
        if ([func performUnaryFunctionWithArg: [itor dereference]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i to be not less than 4723", [[itor dereference] intValue]];
        }
    }
    [func release];
    for ([itor advanceBy: -[v size]], itor2 = [[v begin] advance];
         ![itor2 isEqual: r];
         [itor advance], [itor2 advance])
    {
        if (__indexOf(itor2, v2) < __indexOf(itor, v2))
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i to be not less %i",
                [[itor2 dereference] intValue], [[itor dereference] intValue]];
        }
    }
    for ([itor advance], [itor2 advance];
         ![itor2 isEqual: end];
         [itor advance], [itor2 advance])
    {
        if (__indexOf(itor2, v2) < __indexOf(itor, v2))
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i to be not less %i",
                [[itor2 dereference] intValue], [[itor dereference] intValue]];
        }
    }
    [v release];
    [v2 release];
}

- (void) testStableSort
{
    OLDeque* d;
    OLDeque* d2;
    NSNumber* num;
    NSString* strs[] = { @"yehudi", @"clara", @"helena", @"yehudi", @"clara" };
    NSMutableArray* map;
    NSMutableArray* cur;
    OLGreater* greater;
    int sorted[] = { 1, 4, 2, 0, 3 };
    int i;
    int j;
    int k;
    int next;

    d = [[OLDeque alloc] init];
    for (i = 0; i < 5; i++)
        [d pushBack: strs[i]];
    [OLAlgorithm stableSortFrom: [d begin] to: [d end]];
    for (i = 0; i < 5; i++)
    {
        if ([d at: i] != strs[sorted[i]])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %P, but got %P", strs[sorted[i]], [d at: i]];
        }
    }
    [d clear];
    for (i = 0; i < 10000; i++)
    {
        num = [[NSNumber alloc] initWithInt: lrand48() % 50];
        [d pushBack: num];
        [num release];
    }
    map = [[NSMutableArray alloc] initWithCapacity: 50];
    for (i = 0; i < 50; i++)
    {
        cur = [[NSMutableArray alloc] init];
        for (j = 0; j < 10000; j++)
        {
            if ([[d at: j] intValue] == i)
                [cur addObject: [d at: j]];
        }
        [map addObject: cur];
        [cur release];
    }
    d2 = [[OLDeque alloc] initWithDeque: d];
    [OLAlgorithm stableSortFrom: [d begin] to: [d end]];
    for (i = 0, next = 1; next < 10000; i++, next++)
    {
        if ([[d at: next] intValue] < [[d at: i] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "[%i] %i is less than [%i] %i",
                next, [[d at: next] intValue], i, [[d at: i] intValue]];
        }
    }
    for (i = 0, j = 0; i < 50; i++)
    {
        cur = [map objectAtIndex: i];
        for (k = 0; k < [cur count]; k++, j++)
        {
            if ([d at: j] != [cur objectAtIndex: k])
            {
                [self errInFile: __FILE__ line: __LINE__
                    format: "Expected %P, but got %P", [cur objectAtIndex: k], [d at: j]];
            }
        }
    }
    [d release];
    greater = [[OLGreater alloc] init];
    [OLAlgorithm stableSortFrom: [d2 begin] to: [d2 end] predicate: greater];
    [greater release];
    for (i = 0, next = 1; next < 10000; i++, next++)
    {
        if ([[d2 at: next] intValue] > [[d2 at: i] intValue])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "[%i] %i is greater than [%i] %i",
                next, [[d2 at: next] intValue], i, [[d2 at: i] intValue]];
        }
    }
    for (i = 49, j = 0; i >= 0; i--)
    {
        cur = [map objectAtIndex: i];
        for (k = 0; k < [cur count]; k++, j++)
        {
            if ([d2 at: j] != [cur objectAtIndex: k])
            {
                [self errInFile: __FILE__ line: __LINE__
                    format: "Expected %P, but got %P", [cur objectAtIndex: k], [d2 at: j]];
            }
        }
    }
    [map release];
    [d2 release];
}

- (void) testSwap
{
    NSString* one = @"one";
    NSString* two = @"two";
    OLVector* v;
    OLList* l;

    [OLAlgorithm swap: &one and: &two];
    if (![one isEqual: @"two"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"two\", but got \"%s\"", [one cString]];
    }
    if (![two isEqual: @"one"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"one\", but got \"%s\"", [two cString]];
    }
    [OLAlgorithm swap: &one and: &two];
    v = [[OLVector alloc] init];
    [v pushBack: one];
    [v pushBack: two];
    [OLAlgorithm swapIterators: [v begin] and: [[v end] reverse]];
    if (![[v front] isEqual: @"two"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"two\", but got \"%s\"", [[v front] cString]];
    }
    if (![[v back] isEqual: @"one"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"one\", but got \"%s\"", [[v back] cString]];
    }
    l = [[OLList alloc] init];
    [l pushBack: one];
    [OLAlgorithm swapIterators: [v begin] and: [l begin]];
    if (![[v front] isEqual: @"one"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"one\", but got \"%s\"", [[v front] cString]];
    }
    if (![[l front] isEqual: @"two"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"two\", but got \"%s\"", [[l front] cString]];
    }
    [v release];
    [l release];
}

- (void) testSwapRanges
{
    OLList* l;
    OLVector* v;
    NSNumber* num;
    OLForwardIterator* r;
    OLListIterator* lend;
    OLListIterator* litor;
    int i;

    l = [[OLList alloc] init];
    v = [[OLVector alloc] init];
    [self logMessage: "About to build list"];
    for (i = 0; i < 10000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [l pushBack: num];
        [num release];
    }
    [self logMessage: "Done building list"];
    [self logMessage: "About to build vector"];
    for ( ; i < 20000; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        [v pushBack: num];
        [num release];
    }
    [self logMessage: "Done building vector"];
    lend = [l end];
    litor = [l begin];
    [self logMessage: "About to swap ranges"];
    r = [OLAlgorithm swapRangesFrom: litor to: lend with: [v begin]];
    [self logMessage: "Done swapping ranges"];
    if (![r isEqual: [v end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "The result should be at the end of the vector"];
    }
    for (i = 0; i < 10000; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[v at: i] intValue]];
        }
    }
    for ( ; ![litor isEqual: lend]; [litor advance], i++)
    {
        if ([[litor dereference] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i",
                i, [[litor dereference] intValue]];
        }
    }
    [v release];
    [l release];
}

- (void) testTransform
{
    OLVector* v;
    OLDeque* d;
    OLVector* v2;
    NSString* strs[] = { @"one", @"two", @"three" };
    NSString* strs2[] = { @"yehudi", @"stefanie", @"clara" };
    AppendDoggy* func;
    AppendOther* bfunc;
    OLArrayIterator* abegin;
    OLArrayIterator* aend;
    OLBackInsertIterator* bii;

    abegin = [[OLArrayIterator alloc] initWithPointer: strs];
    aend = [[OLArrayIterator alloc] initWithPointer: strs + 3];
    v = [[OLVector alloc] initFrom: abegin to: aend];
    [abegin release];
    [aend release];
    func = [[AppendDoggy alloc] initWithAutorelease: NO];
    d = [[OLDeque alloc] init];
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: d];
    [OLAlgorithm transformFrom: [v begin] to: [v end] destination: bii function: func];
    [func release];
    if (![[d at: 0] isEqual: @"onedoggy"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"onedoggy\", but got \"%s\"",
            [[d at: 0] cString]];
    }
    if (![[d at: 1] isEqual: @"twodoggy"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"twodoggy\", but got \"%s\"",
            [[d at: 1] cString]];
    }
    if (![[d at: 2] isEqual: @"threedoggy"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"threedoggy\", but got \"%s\"",
            [[d at: 2] cString]];
    }
    [d clear];
    abegin = [[OLArrayIterator alloc] initWithPointer: strs2];
    aend = [[OLArrayIterator alloc] initWithPointer: strs2 + 3];
    v2 = [[OLVector alloc] initFrom: abegin to: aend];
    [abegin release];
    [aend release];
    bfunc = [[AppendOther alloc] initWithAutorelease: NO];
    [OLAlgorithm transformFrom: [v begin] to: [v end] withArgsFrom: [v2 begin]
        destination: bii function: bfunc];
    [bfunc release];
    [v2 release];
    if (![[d at: 0] isEqual: @"oneyehudi"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"oneyehudi\", but got \"%s\"",
            [[d at: 0] cString]];
    }
    if (![[d at: 1] isEqual: @"twostefanie"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"twostefanie\", but got \"%s\"",
            [[d at: 1] cString]];
    }
    if (![[d at: 2] isEqual: @"threeclara"])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected \"threeclara\", but got \"%s\"",
            [[d at: 2] cString]];
    }
    [v release];
    [d release];
    [bii release];
}

- (void) testUnique
{
    OLVector* v;
    NSNumber* num;
    IntCompare* comp;
    OLArrayIterator* begin;
    OLForwardIterator* r;
    int i;
    int j;
    int jmax;
    double i2;

    v = [[OLVector alloc] init];
    for (i = 0; i < 10; i++)
    {
        jmax = lrand48() % 1000 + 1;
        for (j = 0; j < jmax; j++)
        {
            num = [[NSNumber alloc] initWithInt: i];
            [v pushBack: num];
            [num release];
        }
    }
    [self logMessage: "Looking for 10 unique elements from %u", [v size]];
    begin = [v begin];
    r = [OLAlgorithm uniqueFrom: begin to: [v end]];
    if ([OLIterator distanceFrom: begin to: r] != 10)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10, but got %u", [OLIterator distanceFrom: begin to: r]];
    }
    for (i = 0; i < 10; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[v at: i] intValue]];
        }
    }
    [v clear];
    for (i2 = 0.0; i2 < 100.0; i2 += 0.1)
    {
        num = [[NSNumber alloc] initWithDouble: i2];
        [v pushBack: num];
        [num release];
    }
    comp = [[IntCompare alloc] init];
    begin = [v begin];
    r = [OLAlgorithm uniqueFrom: begin to: [v end] predicate: comp];
    if ([OLIterator distanceFrom: begin to: r] != 100)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 100, but got %u", [OLIterator distanceFrom: begin to: r]];
    }
    for (i = 0; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        if (![comp performBinaryFunctionWithArg: [v at: i] andArg: num])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Position %i doesn't test", i];
        }
        [num release];
    }
    [comp release];
    [v release];
}

- (void) testUniqueCopy
{
    OLList* l;
    OLVector* v;
    OLBackInsertIterator* bii;
    NSNumber* num;
    IntCompare* comp;
    int i;
    int j;
    int jmax;
    double i2;

    l = [[OLList alloc] init];
    for (i = 0; i < 10; i++)
    {
        jmax = lrand48() % 1000 + 1;
        for (j = 0; j < jmax; j++)
        {
            num = [[NSNumber alloc] initWithInt: i];
            [l pushBack: num];
            [num release];
        }
    }
    [self logMessage: "Looking for 10 unique elements from %u", [l size]];
    v = [[OLVector alloc] init];
    bii = [[OLBackInsertIterator alloc] initWithBackInserter: v];
    [OLAlgorithm uniqueCopyFrom: [l begin] to: [l end] destination: bii];
    if ([v size] != 10)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 10, but got %u", [v size]];
    }
    for (i = 0; i < 10; i++)
    {
        if ([[v at: i] intValue] != i)
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Expected %i, but got %i", i, [[v at: i] intValue]];
        }
    }
    [l clear];
    [v clear];
    for (i2 = 0.0; i2 < 100.0; i2 += 0.1)
    {
        num = [[NSNumber alloc] initWithDouble: i2];
        [l pushBack: num];
        [num release];
    }
    comp = [[IntCompare alloc] init];
    [OLAlgorithm uniqueCopyFrom: [l begin] to: [l end] destination: bii predicate: comp];
    if ([v size] != 100)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 100, but got %u", [v size]];
    }
    for (i = 0; i < 100; i++)
    {
        num = [[NSNumber alloc] initWithInt: i];
        if (![comp performBinaryFunctionWithArg: [v at: i] andArg: num])
        {
            [self errInFile: __FILE__ line: __LINE__
                format: "Position %i doesn't test", i];
        }
        [num release];
    }
    [comp release];
    [v release];
    [l release];
    [bii release];
}

- (void) testUpperBound
{
    OLList* l;
    NSNumber* num;
    NSNumber* target;
    OLForwardIterator* r;
    OLGreater* greater;
    double i;

    l = [[OLList alloc] init];
    for (i = 0.0; i < 1000.0; i++)
    {
        num = [[NSNumber alloc] initWithDouble: i];
        [l pushBack: num];
        [num release];
    }
    target = [[NSNumber alloc] initWithDouble: 39.5];
    r = [OLAlgorithm upperBoundFrom: [l begin] to: [l end] value: target];
    [target release];
    if ([[r dereference] doubleValue] != 40.0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 999.0, but got %G", [[r dereference] doubleValue]];
    }
    target = [[NSNumber alloc] initWithDouble: 700];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target];
    [target release];
    if ([[r dereference] doubleValue] != 700.0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 700.0, but got %G", [[r dereference] doubleValue]];
    }
    target = [[NSNumber alloc] initWithDouble: 10000.0];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target];
    [target release];
    if (![r isEqual: [l end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected to be at the end"];
    }
    target = [[NSNumber alloc] initWithDouble: -10000.0];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target];
    [target release];
    if (![r isEqual: [l begin]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected to be at the beginning"];
    }
    greater = [[OLGreater alloc] init];
    [l sortWith: greater];
    target = [[NSNumber alloc] initWithDouble: 39.5];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target predicate: greater];
    [target release];
    if ([[r dereference] doubleValue] != 39.0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 40.0, but got %G", [[r dereference] doubleValue]];
    }
    target = [[NSNumber alloc] initWithDouble: 700];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target predicate: greater];
    [target release];
    if ([[r dereference] doubleValue] != 700.0)
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected 700.0, but got %G", [[r dereference] doubleValue]];
    }
    target = [[NSNumber alloc] initWithDouble: 10000.0];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target predicate: greater];
    [target release];
    if (![r isEqual: [l begin]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected to be at the beginning"];
    }
    target = [[NSNumber alloc] initWithDouble: -10000.0];
    r = [OLAlgorithm lowerBoundFrom: [l begin] to: [l end] value: target predicate: greater];
    [target release];
    if (![r isEqual: [l end]])
    {
        [self errInFile: __FILE__ line: __LINE__
            format: "Expected to be at the end"];
    }
    [greater release];
    [l release];
}

@end
