The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
CONTRIBUTING 700
CONTRIBUTING.mkdn 087
Changes 09
LICENSE 11
MANIFEST 13
META.json 1214
META.yml 1718
Makefile.PL 76
README 22
cpanfile 68
dist.ini 11
lib/Test/Number/Delta.pm 22220
perlcritic.rc 03
t/00-report-prereqs.dd 050
t/00-report-prereqs.t 95144
t/04-specify_relative.t 315
t/11-specify_negative_relative.t 22
xt/author/00-compile.t 58
xt/author/pod-spell.t 11
xt/release/distmeta.t 32
xt/release/pod-coverage.t 93
xt/release/pod-syntax.t 32
xt/release/test-version.t 22
23 files changed (This is a version diff) 262601
@@ -1,70 +0,0 @@
-## HOW TO CONTRIBUTE
-
-Thank you for considering contributing to this distribution.  This file
-contains instructions that will help you work with the source code.
-
-The distribution is managed with Dist::Zilla.  This means than many of the
-usual files you might expect are not in the repository, but are generated
-at release time (e.g. Makefile.PL).
-
-### Getting dependencies
-
-See the included `cpanfile` file for a list of dependencies.  If you have
-App::cpanminus 1.6 or later installed, you can use `cpanm` to satisfy
-dependencies like this:
-
-    $ cpanm --installdeps .
-
-Otherwise, you can install Module::CPANfile 1.0002 or later and then satisfy
-dependencies with the regular `cpan` client and `cpanfile-dump`:
-
-    $ cpan `cpanfile-dump`
-
-### Running tests
-
-You can run tests directly using the `prove` tool:
-
-    $ prove -l
-    $ prove -lv t/some_test_file.t
-
-For most distributions, `prove` is entirely sufficent for you to test any
-patches you have.
-
-### Code style and tidying
-
-Please try to match any existing coding style.  If there is a `.perltidyrc`
-file, please install Perl::Tidy and use perltidy before submitting patches.
-
-If there is a `tidyall.ini` file, you can also install Code::TidyAll and run
-`tidyall` on a file or `tidyall -a` to tidy all files.
-
-### Patching documentation
-
-Much of the documentation Pod is generated at release time.
-Depending on the distribution, some documentation may be written in a Pod
-dialect called WikiDoc. (See Pod::WikiDoc on CPAN.)
-
-If you would like to submit a documentation edit, please limit yourself to the
-documentation you see.
-
-If you see typos or documentation issues in the generated docs, please
-email or open a bug ticket instead of patching.
-
-### Learning Dist::Zilla
-
-Dist::Zilla is a very powerful authoring tool, but requires a number of
-author-specific plugins.  If you would like to use it for contributing,
-install it from CPAN, then run one of the following commands, depending on
-your CPAN client:
-
-    $ cpan `dzil authordeps`
-    $ dzil authordeps | cpanm
-
-Once installed, here are some dzil commands you might try:
-
-    $ dzil build
-    $ dzil test
-    $ dzil xtest
-
-You can learn more about Dist::Zilla at http://dzil.org/
-
@@ -0,0 +1,87 @@
+## HOW TO CONTRIBUTE
+
+Thank you for considering contributing to this distribution.  This file
+contains instructions that will help you work with the source code.
+
+The distribution is managed with Dist::Zilla.  This means than many of the
+usual files you might expect are not in the repository, but are generated at
+release time, as is much of the documentation.  Some generated files are
+kept in the repository as a convenience (e.g. Makefile.PL or cpanfile).
+
+Generally, **you do not need Dist::Zilla to contribute patches**.  You do need
+Dist::Zilla to create a tarball.  See below for guidance.
+
+### Getting dependencies
+
+If you have App::cpanminus 1.6 or later installed, you can use `cpanm` to
+satisfy dependencies like this:
+
+    $ cpanm --installdeps .
+
+Otherwise, look for either a `Makefile.PL` or `cpanfile` file for
+a list of dependencies to satisfy.
+
+### Running tests
+
+You can run tests directly using the `prove` tool:
+
+    $ prove -l
+    $ prove -lv t/some_test_file.t
+
+For most of my distributions, `prove` is entirely sufficient for you to test any
+patches you have. I use `prove` for 99% of my testing during development.
+
+### Code style and tidying
+
+Please try to match any existing coding style.  If there is a `.perltidyrc`
+file, please install Perl::Tidy and use perltidy before submitting patches.
+
+If there is a `tidyall.ini` file, you can also install Code::TidyAll and run
+`tidyall` on a file or `tidyall -a` to tidy all files.
+
+### Patching documentation
+
+Much of the documentation Pod is generated at release time.  Some is
+generated boilerplate; other documentation is built from pseudo-POD
+directives in the source like C<=method> or C<=func>.
+
+If you would like to submit a documentation edit, please limit yourself to
+the documentation you see.
+
+If you see typos or documentation issues in the generated docs, please
+email or open a bug ticket instead of patching.
+
+### Installing and using Dist::Zilla
+
+Dist::Zilla is a very powerful authoring tool, optimized for maintaining a
+large number of distributions with a high degree of automation, but it has a
+large dependency chain, a bit of a learning curve and requires a number of
+author-specific plugins.
+
+To install it from CPAN, I recommend one of the following approaches for
+the quickest installation:
+
+    # using CPAN.pm, but bypassing non-functional pod tests
+    $ cpan TAP::Harness::Restricted
+    $ PERL_MM_USE_DEFAULT=1 HARNESS_CLASS=TAP::Harness::Restricted cpan Dist::Zilla
+
+    # using cpanm, bypassing *all* tests
+    $ cpanm -n Dist::Zilla
+
+In either case, it's probably going to take about 10 minutes.  Go for a walk,
+go get a cup of your favorite beverage, take a bathroom break, or whatever.
+When you get back, Dist::Zilla should be ready for you.
+
+Then you need to install any plugins specific to this distribution:
+
+    $ cpan `dzil authordeps`
+    $ dzil authordeps | cpanm
+
+Once installed, here are some dzil commands you might try:
+
+    $ dzil build
+    $ dzil test
+    $ dzil xtest
+
+You can learn more about Dist::Zilla at http://dzil.org/
+
@@ -1,5 +1,14 @@
 Revision history for Perl module Test::Number::Delta
 
+1.05      2014-11-24 11:08:11-05:00 America/New_York
+
+    [Fixed]
+
+    - relative comparison of array reference elements now works as intended
+
+    - diagnostics of delta_not_ok and delta_not_within clarified under
+      relative comparison
+
 1.04      2013-11-20 18:43:32 America/New_York
 
     - Modernized distribution metadata and licensing
@@ -1,4 +1,4 @@
-This software is Copyright (c) 2013 by David Golden.
+This software is Copyright (c) 2014 by David Golden.
 
 This is free software, licensed under:
 
@@ -1,4 +1,5 @@
-CONTRIBUTING
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.025.
+CONTRIBUTING.mkdn
 Changes
 LICENSE
 MANIFEST
@@ -10,6 +11,7 @@ cpanfile
 dist.ini
 lib/Test/Number/Delta.pm
 perlcritic.rc
+t/00-report-prereqs.dd
 t/00-report-prereqs.t
 t/01-module-basics.t
 t/02-delta.t
@@ -4,7 +4,7 @@
       "David Golden <dagolden@cpan.org>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Dist::Zilla version 5.006, CPAN::Meta::Converter version 2.132830",
+   "generated_by" : "Dist::Zilla version 5.025, CPAN::Meta::Converter version 2.142690",
    "license" : [
       "apache_2_0"
    ],
@@ -27,13 +27,14 @@
    "prereqs" : {
       "configure" : {
          "requires" : {
-            "ExtUtils::MakeMaker" : "6.17"
+            "ExtUtils::MakeMaker" : "6.17",
+            "perl" : "5.006"
          }
       },
       "develop" : {
          "requires" : {
-            "Dist::Zilla" : "5.006",
-            "Dist::Zilla::PluginBundle::DAGOLDEN" : "0.059",
+            "Dist::Zilla" : "5",
+            "Dist::Zilla::PluginBundle::DAGOLDEN" : "0.072",
             "File::Spec" : "0",
             "File::Temp" : "0",
             "IO::Handle" : "0",
@@ -42,7 +43,9 @@
             "Test::CPAN::Meta" : "0",
             "Test::More" : "0",
             "Test::Pod" : "1.41",
-            "Test::Pod::Coverage" : "1.08"
+            "Test::Pod::Coverage" : "1.08",
+            "Test::Spelling" : "0.12",
+            "Test::Version" : "1"
          }
       },
       "runtime" : {
@@ -58,22 +61,21 @@
       },
       "test" : {
          "recommends" : {
-            "CPAN::Meta" : "0",
-            "CPAN::Meta::Requirements" : "0"
+            "CPAN::Meta" : "2.120900"
          },
          "requires" : {
             "ExtUtils::MakeMaker" : "0",
-            "File::Spec::Functions" : "0",
-            "List::Util" : "0",
+            "File::Spec" : "0",
             "Test::Builder::Tester" : "1.02",
-            "Test::More" : "0"
+            "Test::More" : "0",
+            "perl" : "5.006"
          }
       }
    },
    "provides" : {
       "Test::Number::Delta" : {
          "file" : "lib/Test/Number/Delta.pm",
-         "version" : "1.04"
+         "version" : "1.05"
       }
    },
    "release_status" : "stable",
@@ -88,7 +90,7 @@
          "web" : "https://github.com/dagolden/Test-Number-Delta"
       }
    },
-   "version" : "1.04",
+   "version" : "1.05",
    "x_authority" : "cpan:DAGOLDEN"
 }
 
@@ -3,19 +3,20 @@ abstract: 'Compare the difference between numbers against a given tolerance'
 author:
   - 'David Golden <dagolden@cpan.org>'
 build_requires:
-  ExtUtils::MakeMaker: 0
-  File::Spec::Functions: 0
-  List::Util: 0
-  Test::Builder::Tester: 1.02
-  Test::More: 0
+  ExtUtils::MakeMaker: '0'
+  File::Spec: '0'
+  Test::Builder::Tester: '1.02'
+  Test::More: '0'
+  perl: '5.006'
 configure_requires:
-  ExtUtils::MakeMaker: 6.17
+  ExtUtils::MakeMaker: '6.17'
+  perl: '5.006'
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 5.006, CPAN::Meta::Converter version 2.132830'
+generated_by: 'Dist::Zilla version 5.025, CPAN::Meta::Converter version 2.142690'
 license: apache
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
-  version: 1.4
+  version: '1.4'
 name: Test-Number-Delta
 no_index:
   directory:
@@ -28,18 +29,18 @@ no_index:
 provides:
   Test::Number::Delta:
     file: lib/Test/Number/Delta.pm
-    version: 1.04
+    version: '1.05'
 requires:
-  Carp: 0
-  Exporter: 0
-  Test::Builder: 0
-  perl: 5.006
-  strict: 0
-  vars: 0
-  warnings: 0
+  Carp: '0'
+  Exporter: '0'
+  Test::Builder: '0'
+  perl: '5.006'
+  strict: '0'
+  vars: '0'
+  warnings: '0'
 resources:
   bugtracker: https://github.com/dagolden/Test-Number-Delta/issues
   homepage: https://github.com/dagolden/Test-Number-Delta
   repository: https://github.com/dagolden/Test-Number-Delta.git
-version: 1.04
+version: '1.05'
 x_authority: cpan:DAGOLDEN
@@ -1,4 +1,5 @@
 
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.025.
 use strict;
 use warnings;
 
@@ -11,13 +12,13 @@ use ExtUtils::MakeMaker 6.17;
 my %WriteMakefileArgs = (
   "ABSTRACT" => "Compare the difference between numbers against a given tolerance",
   "AUTHOR" => "David Golden <dagolden\@cpan.org>",
-  "BUILD_REQUIRES" => {},
   "CONFIGURE_REQUIRES" => {
     "ExtUtils::MakeMaker" => "6.17"
   },
   "DISTNAME" => "Test-Number-Delta",
   "EXE_FILES" => [],
   "LICENSE" => "apache",
+  "MIN_PERL_VERSION" => "5.006",
   "NAME" => "Test::Number::Delta",
   "PREREQ_PM" => {
     "Carp" => 0,
@@ -29,12 +30,11 @@ my %WriteMakefileArgs = (
   },
   "TEST_REQUIRES" => {
     "ExtUtils::MakeMaker" => 0,
-    "File::Spec::Functions" => 0,
-    "List::Util" => 0,
+    "File::Spec" => 0,
     "Test::Builder::Tester" => "1.02",
     "Test::More" => 0
   },
-  "VERSION" => "1.04",
+  "VERSION" => "1.05",
   "test" => {
     "TESTS" => "t/*.t"
   }
@@ -44,9 +44,8 @@ my %WriteMakefileArgs = (
 my %FallbackPrereqs = (
   "Carp" => 0,
   "Exporter" => 0,
-  "ExtUtils::MakeMaker" => 0,
-  "File::Spec::Functions" => 0,
-  "List::Util" => 0,
+  "ExtUtils::MakeMaker" => "6.17",
+  "File::Spec" => 0,
   "Test::Builder" => 0,
   "Test::Builder::Tester" => "1.02",
   "Test::More" => 0,
@@ -3,7 +3,7 @@ NAME
     given tolerance
 
 VERSION
-    version 1.04
+    version 1.05
 
 SYNOPSIS
       # Import test functions
@@ -170,7 +170,7 @@ AUTHOR
     David Golden <dagolden@cpan.org>
 
 COPYRIGHT AND LICENSE
-    This software is Copyright (c) 2013 by David Golden.
+    This software is Copyright (c) 2014 by David Golden.
 
     This is free software, licensed under:
 
@@ -8,24 +8,24 @@ requires "warnings" => "0";
 
 on 'test' => sub {
   requires "ExtUtils::MakeMaker" => "0";
-  requires "File::Spec::Functions" => "0";
-  requires "List::Util" => "0";
+  requires "File::Spec" => "0";
   requires "Test::Builder::Tester" => "1.02";
   requires "Test::More" => "0";
+  requires "perl" => "5.006";
 };
 
 on 'test' => sub {
-  recommends "CPAN::Meta" => "0";
-  recommends "CPAN::Meta::Requirements" => "0";
+  recommends "CPAN::Meta" => "2.120900";
 };
 
 on 'configure' => sub {
   requires "ExtUtils::MakeMaker" => "6.17";
+  requires "perl" => "5.006";
 };
 
 on 'develop' => sub {
-  requires "Dist::Zilla" => "5.006";
-  requires "Dist::Zilla::PluginBundle::DAGOLDEN" => "0.059";
+  requires "Dist::Zilla" => "5";
+  requires "Dist::Zilla::PluginBundle::DAGOLDEN" => "0.072";
   requires "File::Spec" => "0";
   requires "File::Temp" => "0";
   requires "IO::Handle" => "0";
@@ -35,4 +35,6 @@ on 'develop' => sub {
   requires "Test::More" => "0";
   requires "Test::Pod" => "1.41";
   requires "Test::Pod::Coverage" => "1.08";
+  requires "Test::Spelling" => "0.12";
+  requires "Test::Version" => "1";
 };
@@ -4,4 +4,4 @@ license = Apache_2_0
 copyright_holder = David Golden
 
 [@DAGOLDEN]
-:version = 0.059
+:version = 0.072
@@ -3,7 +3,8 @@ use warnings;
 
 package Test::Number::Delta;
 # ABSTRACT: Compare the difference between numbers against a given tolerance
-our $VERSION = '1.04'; # VERSION
+
+our $VERSION = '1.05';
 
 use vars qw (@EXPORT @ISA);
 
@@ -15,6 +16,103 @@ use Exporter;
 @ISA    = qw( Exporter );
 @EXPORT = qw( delta_not_ok delta_ok delta_within delta_not_within );
 
+#pod =head1 SYNOPSIS
+#pod
+#pod   # Import test functions
+#pod   use Test::Number::Delta;
+#pod
+#pod   # Equality test with default tolerance
+#pod   delta_ok( 1e-5, 2e-5, 'values within 1e-6');
+#pod
+#pod   # Inequality test with default tolerance
+#pod   delta_not_ok( 1e-5, 2e-5, 'values not within 1e-6');
+#pod
+#pod   # Provide specific tolerance
+#pod   delta_within( 1e-3, 2e-3, 1e-4, 'values within 1e-4');
+#pod   delta_not_within( 1e-3, 2e-3, 1e-4, 'values not within 1e-4');
+#pod
+#pod   # Compare arrays or matrices
+#pod   @a = ( 3.14, 1.41 );
+#pod   @b = ( 3.15, 1.41 );
+#pod   delta_ok( \@a, \@b, 'compare @a and @b' );
+#pod
+#pod   # Set a different default tolerance
+#pod   use Test::Number::Delta within => 1e-5;
+#pod   delta_ok( 1.1e-5, 2e-5, 'values within 1e-5'); # ok
+#pod
+#pod   # Set a relative tolerance
+#pod   use Test::Number::Delta relative => 1e-3;
+#pod   delta_ok( 1.01, 1.0099, 'values within 1.01e-3');
+#pod
+#pod
+#pod =head1 DESCRIPTION
+#pod
+#pod At some point or another, most programmers find they need to compare
+#pod floating-point numbers for equality.  The typical idiom is to test
+#pod if the absolute value of the difference of the numbers is within a desired
+#pod tolerance, usually called epsilon.  This module provides such a function for use
+#pod with L<Test::More>.  Usage is similar to other test functions described in
+#pod L<Test::More>.  Semantically, the C<delta_within> function replaces this kind
+#pod of construct:
+#pod
+#pod  ok ( abs($p - $q) < $epsilon, '$p is equal to $q' ) or
+#pod      diag "$p is not equal to $q to within $epsilon";
+#pod
+#pod While there's nothing wrong with that construct, it's painful to type it
+#pod repeatedly in a test script.  This module does the same thing with a single
+#pod function call.  The C<delta_ok> function is similar, but either uses a global
+#pod default value for epsilon or else calculates a 'relative' epsilon on
+#pod the fly so that epsilon is scaled automatically to the size of the arguments to
+#pod C<delta_ok>.  Both functions are exported automatically.
+#pod
+#pod Because checking floating-point equality is not always reliable, it is not
+#pod possible to check the 'equal to' boundary of 'less than or equal to
+#pod epsilon'.  Therefore, Test::Number::Delta only compares if the absolute value
+#pod of the difference is B<less than> epsilon (for equality tests) or
+#pod B<greater than> epsilon (for inequality tests).
+#pod
+#pod =head1 USAGE
+#pod
+#pod =head2 use Test::Number::Delta;
+#pod
+#pod With no arguments, epsilon defaults to 1e-6. (An arbitrary choice on the
+#pod author's part.)
+#pod
+#pod =head2 use Test::Number::Delta within => 1e-9;
+#pod
+#pod To specify a different default value for epsilon, provide a C<within> parameter
+#pod when importing the module.  The value must be non-zero.
+#pod
+#pod =head2 use Test::Number::Delta relative => 1e-3;
+#pod
+#pod As an alternative to using a fixed value for epsilon, provide a C<relative>
+#pod parameter when importing the module.  This signals that C<delta_ok> should
+#pod test equality with an epsilon that is scaled to the size of the arguments.
+#pod Epsilon is calculated as the relative value times the absolute value
+#pod of the argument with the greatest magnitude.  Mathematically, for arguments
+#pod 'x' and 'y':
+#pod
+#pod  epsilon = relative * max( abs(x), abs(y) )
+#pod
+#pod For example, a relative value of "0.01" would mean that the arguments are equal
+#pod if they differ by less than 1% of the larger of the two values.  A relative
+#pod value of 1e-6 means that the arguments must differ by less than 1 millionth
+#pod of the larger value.  The relative value must be non-zero.
+#pod
+#pod =head2 Combining with a test plan
+#pod
+#pod  use Test::Number::Delta 'no_plan';
+#pod
+#pod  # or
+#pod
+#pod  use Test::Number::Delta within => 1e-9, tests => 1;
+#pod
+#pod If a test plan has not already been specified, the optional
+#pod parameter for Test::Number::Delta may be followed with a test plan (see
+#pod L<Test::More> for details).  If a parameter for Test::Number::Delta is
+#pod given, it must come first.
+#pod
+#pod =cut
 
 my $Test     = Test::Builder->new;
 my $Epsilon  = 1e-6;
@@ -50,14 +148,26 @@ sub import {
 #--------------------------------------------------------------------------#
 
 sub _check {
-    my ( $p, $q, $epsilon, $name, @indices ) = @_;
+    my ( $p, $q, $e, $name, @indices ) = @_;
+    my $epsilon;
+
+    if ( !defined $e ) {
+        $epsilon =
+            $Relative
+          ? $Relative * ( abs($p) > abs($q) ? abs($p) : abs($q) )
+          : $Epsilon;
+    }
+    else {
+        $epsilon = abs($e);
+    }
+
     my ( $ok, $diag ) = ( 1, q{} ); # assume true
     if ( ref $p eq 'ARRAY' || ref $q eq 'ARRAY' ) {
         if ( @$p == @$q ) {
             for my $i ( 0 .. $#{$p} ) {
                 my @new_indices;
-                ( $ok, $diag, @new_indices ) = _check( $p->[$i], $q->[$i], $epsilon, $name,
-                    scalar @indices ? @indices : (), $i, );
+                ( $ok, $diag, @new_indices ) =
+                  _check( $p->[$i], $q->[$i], $e, $name, scalar @indices ? @indices : (), $i, );
                 if ( not $ok ) {
                     @indices = @new_indices;
                     last;
@@ -85,24 +195,78 @@ sub _check {
 }
 
 sub _ep_dp {
-    my $epsilon = shift;
+    my $epsilon = shift
+      or return;
+    $epsilon = abs($epsilon);
     my ($exp) = sprintf( "%e", $epsilon ) =~ m/e(.+)/;
     my $ep = $exp < 0 ? -$exp : 1;
     my $dp = $ep + 1;
     return ( $ep, $dp );
 }
 
+sub _diag_default {
+    my ($ep) = _ep_dp( abs( $Relative || $Epsilon ) );
+    my $diag = "Arguments are equal to within ";
+    $diag .=
+      $Relative
+      ? sprintf( "relative tolerance %.${ep}f", abs($Relative) )
+      : sprintf( "%.${ep}f",                    abs($Epsilon) );
+    return $diag;
+}
+
+#pod =head1 FUNCTIONS
+#pod
+#pod =cut
 
 #--------------------------------------------------------------------------#
 # delta_within()
 #--------------------------------------------------------------------------#
 
+#pod =head2 delta_within
+#pod
+#pod  delta_within(  $p,  $q, $epsilon, '$p and $q are equal within $epsilon' );
+#pod  delta_within( \@p, \@q, $epsilon, '@p and @q are equal within $epsilon' );
+#pod
+#pod This function tests for equality within a given value of epsilon. The test is
+#pod true if the absolute value of the difference between $p and $q is B<less than>
+#pod epsilon.  If the test is true, it prints an "OK" statement for use in testing.
+#pod If the test is not true, this function prints a failure report and diagnostic.
+#pod Epsilon must be non-zero.
+#pod
+#pod The values to compare may be scalars or references to arrays.  If the values
+#pod are references to arrays, the comparison is done pairwise for each index value
+#pod of the array.  The pairwise comparison is recursive, so matrices may
+#pod be compared as well.
+#pod
+#pod For example, this code sample compares two matrices:
+#pod
+#pod     my @a = (   [ 3.14, 6.28 ],
+#pod                 [ 1.41, 2.84 ]   );
+#pod
+#pod     my @b = (   [ 3.14, 6.28 ],
+#pod                 [ 1.42, 2.84 ]   );
+#pod
+#pod     delta_within( \@a, \@b, 1e-6, 'compare @a and @b' );
+#pod
+#pod The sample prints the following:
+#pod
+#pod     not ok 1 - compare @a and @b
+#pod     # At [1][0]: 1.4100000 and 1.4200000 are not equal to within 0.000001
+#pod
+#pod =cut
 
 sub delta_within($$$;$) { ## no critic
     my ( $p, $q, $epsilon, $name ) = @_;
     croak "Value of epsilon to delta_within must be non-zero"
-      if $epsilon == 0;
-    $epsilon = abs($epsilon);
+      if !defined($epsilon) || $epsilon == 0;
+    {
+        local $Test::Builder::Level = $Test::Builder::Level + 1;
+        _delta_within( $p, $q, $epsilon, $name );
+    }
+}
+
+sub _delta_within {
+    my ( $p, $q, $epsilon, $name ) = @_;
     my ( $ok, $diag, @indices ) = _check( $p, $q, $epsilon, $name );
     if (@indices) {
         $diag = "At [" . join( "][", @indices ) . "]: $diag";
@@ -114,16 +278,22 @@ sub delta_within($$$;$) { ## no critic
 # delta_ok()
 #--------------------------------------------------------------------------#
 
+#pod =head2 delta_ok
+#pod
+#pod  delta_ok(  $p,  $q, '$p and $q are close enough to equal' );
+#pod  delta_ok( \@p, \@q, '@p and @q are close enough to equal' );
+#pod
+#pod This function tests for equality within a default epsilon value.  See L</USAGE>
+#pod for details on changing the default.  Otherwise, this function works the same
+#pod as C<delta_within>.
+#pod
+#pod =cut
 
 sub delta_ok($$;$) { ## no critic
     my ( $p, $q, $name ) = @_;
     {
         local $Test::Builder::Level = $Test::Builder::Level + 1;
-        my $e =
-            $Relative
-          ? $Relative * ( abs($p) > abs($q) ? abs($p) : abs($q) )
-          : $Epsilon;
-        delta_within( $p, $q, $e, $name );
+        _delta_within( $p, $q, undef, $name );
     }
 }
 
@@ -131,29 +301,57 @@ sub delta_ok($$;$) { ## no critic
 # delta_not_ok()
 #--------------------------------------------------------------------------#
 
+#pod =head2 delta_not_within
+#pod
+#pod  delta_not_within(  $p,  $q, '$p and $q are different' );
+#pod  delta_not_within( \@p, \@q, $epsilon, '@p and @q are different' );
+#pod
+#pod This test compares inequality in excess of a given value of epsilon. The test
+#pod is true if the absolute value of the difference between $p and $q is B<greater
+#pod than> epsilon.  For array or matrix comparisons, the test is true if I<any>
+#pod pair of values differs by more than epsilon.  Otherwise, this function works
+#pod the same as C<delta_within>.
+#pod
+#pod =cut
 
 sub delta_not_within($$$;$) { ## no critic
     my ( $p, $q, $epsilon, $name ) = @_;
     croak "Value of epsilon to delta_not_within must be non-zero"
-      if $epsilon == 0;
-    $epsilon = abs($epsilon);
+      if !defined($epsilon) || $epsilon == 0;
+    {
+        local $Test::Builder::Level = $Test::Builder::Level + 1;
+        _delta_not_within( $p, $q, $epsilon, $name );
+    }
+}
+
+sub _delta_not_within($$$;$) { ## no critic
+    my ( $p, $q, $epsilon, $name ) = @_;
     my ( $ok, undef, @indices ) = _check( $p, $q, $epsilon, $name );
     $ok = !$ok;
     my ( $ep, $dp ) = _ep_dp($epsilon);
-    my $diag = sprintf( "Arguments are equal to within %.${ep}f", $epsilon );
+    my $diag =
+      defined($epsilon)
+      ? sprintf( "Arguments are equal to within %.${ep}f", abs($epsilon) )
+      : _diag_default();
     return $Test->ok( $ok, $name ) || $Test->diag($diag);
 }
 
+#pod =head2 delta_not_ok
+#pod
+#pod  delta_not_ok(  $p,  $q, '$p and $q are different' );
+#pod  delta_not_ok( \@p, \@q, '@p and @q are different' );
+#pod
+#pod This function tests for inequality in excess of a default epsilon value.  See
+#pod L</USAGE> for details on changing the default.  Otherwise, this function works
+#pod the same as C<delta_not_within>.
+#pod
+#pod =cut
 
 sub delta_not_ok($$;$) { ## no critic
     my ( $p, $q, $name ) = @_;
     {
         local $Test::Builder::Level = $Test::Builder::Level + 1;
-        my $e =
-            $Relative
-          ? $Relative * ( abs($p) > abs($q) ? abs($p) : abs($q) )
-          : $Epsilon;
-        delta_not_within( $p, $q, $e, $name );
+        _delta_not_within( $p, $q, undef, $name );
     }
 }
 
@@ -171,7 +369,7 @@ Test::Number::Delta - Compare the difference between numbers against a given tol
 
 =head1 VERSION
 
-version 1.04
+version 1.05
 
 =head1 SYNOPSIS
 
@@ -355,7 +553,7 @@ David Golden <dagolden@cpan.org>
 
 =head1 COPYRIGHT AND LICENSE
 
-This software is Copyright (c) 2013 by David Golden.
+This software is Copyright (c) 2014 by David Golden.
 
 This is free software, licensed under:
 
@@ -7,6 +7,9 @@ allow = $@ $!
 [TestingAndDebugging::ProhibitNoStrict]
 allow = refs
 
+[Variables::ProhibitEvilVariables]
+variables = $DB::single
+
 # Turn these off
 [-BuiltinFunctions::ProhibitStringyEval]
 [-ControlStructures::ProhibitPostfixControls]
@@ -0,0 +1,50 @@
+do { my $x = {
+       'configure' => {
+                        'requires' => {
+                                        'ExtUtils::MakeMaker' => '6.17',
+                                        'perl' => '5.006'
+                                      }
+                      },
+       'develop' => {
+                      'requires' => {
+                                      'Dist::Zilla' => '5',
+                                      'Dist::Zilla::PluginBundle::DAGOLDEN' => '0.072',
+                                      'File::Spec' => '0',
+                                      'File::Temp' => '0',
+                                      'IO::Handle' => '0',
+                                      'IPC::Open3' => '0',
+                                      'Pod::Coverage::TrustPod' => '0',
+                                      'Test::CPAN::Meta' => '0',
+                                      'Test::More' => '0',
+                                      'Test::Pod' => '1.41',
+                                      'Test::Pod::Coverage' => '1.08',
+                                      'Test::Spelling' => '0.12',
+                                      'Test::Version' => '1'
+                                    }
+                    },
+       'runtime' => {
+                      'requires' => {
+                                      'Carp' => '0',
+                                      'Exporter' => '0',
+                                      'Test::Builder' => '0',
+                                      'perl' => '5.006',
+                                      'strict' => '0',
+                                      'vars' => '0',
+                                      'warnings' => '0'
+                                    }
+                    },
+       'test' => {
+                   'recommends' => {
+                                     'CPAN::Meta' => '2.120900'
+                                   },
+                   'requires' => {
+                                   'ExtUtils::MakeMaker' => '0',
+                                   'File::Spec' => '0',
+                                   'Test::Builder::Tester' => '1.02',
+                                   'Test::More' => '0',
+                                   'perl' => '5.006'
+                                 }
+                 }
+     };
+  $x;
+ }
\ No newline at end of file
@@ -3,125 +3,174 @@
 use strict;
 use warnings;
 
-# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.010
+# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.019
 
 use Test::More tests => 1;
 
 use ExtUtils::MakeMaker;
-use File::Spec::Functions;
-use List::Util qw/max/;
-
-my @modules = qw(
-  CPAN::Meta
-  CPAN::Meta::Requirements
-  Carp
-  Exporter
-  ExtUtils::MakeMaker
-  File::Spec::Functions
-  List::Util
-  Test::Builder
-  Test::Builder::Tester
-  Test::More
-  perl
-  strict
-  vars
-  warnings
+use File::Spec;
+
+# from $version::LAX
+my $lax_version_re =
+    qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )?
+            |
+            (?:\.[0-9]+) (?:_[0-9]+)?
+        ) | (?:
+            v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )?
+            |
+            (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)?
+        )
+    )/x;
+
+# hide optional CPAN::Meta modules from prereq scanner
+# and check if they are available
+my $cpan_meta = "CPAN::Meta";
+my $cpan_meta_pre = "CPAN::Meta::Prereqs";
+my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic
+
+# Verify requirements?
+my $DO_VERIFY_PREREQS = 1;
+
+sub _max {
+    my $max = shift;
+    $max = ( $_ > $max ) ? $_ : $max for @_;
+    return $max;
+}
+
+sub _merge_prereqs {
+    my ($collector, $prereqs) = @_;
+
+    # CPAN::Meta::Prereqs object
+    if (ref $collector eq $cpan_meta_pre) {
+        return $collector->with_merged_prereqs(
+            CPAN::Meta::Prereqs->new( $prereqs )
+        );
+    }
+
+    # Raw hashrefs
+    for my $phase ( keys %$prereqs ) {
+        for my $type ( keys %{ $prereqs->{$phase} } ) {
+            for my $module ( keys %{ $prereqs->{$phase}{$type} } ) {
+                $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module};
+            }
+        }
+    }
+
+    return $collector;
+}
+
+my @include = qw(
+
 );
 
-my %exclude = map {; $_ => 1 } qw(
+my @exclude = qw(
 
 );
 
-my ($source) = grep { -f $_ } qw/MYMETA.json MYMETA.yml META.json/;
-$source = "META.yml" unless defined $source;
+# Add static prereqs to the included modules list
+my $static_prereqs = do 't/00-report-prereqs.dd';
 
-# replace modules with dynamic results from MYMETA.json if we can
-# (hide CPAN::Meta from prereq scanner)
-my $cpan_meta = "CPAN::Meta";
-my $cpan_meta_req = "CPAN::Meta::Requirements";
-my $all_requires;
-if ( -f $source && eval "require $cpan_meta" ) { ## no critic
-  if ( my $meta = eval { CPAN::Meta->load_file($source) } ) {
-
-    # Get ALL modules mentioned in META (any phase/type)
-    my $prereqs = $meta->prereqs;
-    delete $prereqs->{develop} if not $ENV{AUTHOR_TESTING};
-    my %uniq = map {$_ => 1} map { keys %$_ } map { values %$_ } values %$prereqs;
-    $uniq{$_} = 1 for @modules; # don't lose any static ones
-    @modules = sort grep { ! $exclude{$_} } keys %uniq;
-
-    # If verifying, merge 'requires' only for major phases
-    if ( 1 ) {
-      $prereqs = $meta->effective_prereqs; # get the object, not the hash
-      if (eval "require $cpan_meta_req; 1") { ## no critic
-        $all_requires = $cpan_meta_req->new;
-        for my $phase ( qw/configure build test runtime/ ) {
-          $all_requires->add_requirements(
-            $prereqs->requirements_for($phase, 'requires')
-          );
-        }
-      }
+# Merge all prereqs (either with ::Prereqs or a hashref)
+my $full_prereqs = _merge_prereqs(
+    ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ),
+    $static_prereqs
+);
+
+# Add dynamic prereqs to the included modules list (if we can)
+my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml';
+if ( $source && $HAS_CPAN_META ) {
+    if ( my $meta = eval { CPAN::Meta->load_file($source) } ) {
+        $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs);
     }
-  }
+}
+else {
+    $source = 'static metadata';
 }
 
-my @reports = [qw/Version Module/];
+my @full_reports;
 my @dep_errors;
-my $req_hash = defined($all_requires) ? $all_requires->as_string_hash : {};
-
-for my $mod ( @modules ) {
-  next if $mod eq 'perl';
-  my $file = $mod;
-  $file =~ s{::}{/}g;
-  $file .= ".pm";
-  my ($prefix) = grep { -e catfile($_, $file) } @INC;
-  if ( $prefix ) {
-    my $ver = MM->parse_version( catfile($prefix, $file) );
-    $ver = "undef" unless defined $ver; # Newer MM should do this anyway
-    push @reports, [$ver, $mod];
-
-    if ( 1 && $all_requires ) {
-      my $req = $req_hash->{$mod};
-      if ( defined $req && length $req ) {
-        if ( ! defined eval { version->parse($ver) } ) {
-          push @dep_errors, "$mod version '$ver' cannot be parsed (version '$req' required)";
-        }
-        elsif ( ! $all_requires->accepts_module( $mod => $ver ) ) {
-          push @dep_errors, "$mod version '$ver' is not in required range '$req'";
+my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs;
+
+# Add static includes into a fake section
+for my $mod (@include) {
+    $req_hash->{other}{modules}{$mod} = 0;
+}
+
+for my $phase ( qw(configure build test runtime develop other) ) {
+    next unless $req_hash->{$phase};
+    next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING});
+
+    for my $type ( qw(requires recommends suggests conflicts modules) ) {
+        next unless $req_hash->{$phase}{$type};
+
+        my $title = ucfirst($phase).' '.ucfirst($type);
+        my @reports = [qw/Module Want Have/];
+
+        for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) {
+            next if $mod eq 'perl';
+            next if grep { $_ eq $mod } @exclude;
+
+            my $file = $mod;
+            $file =~ s{::}{/}g;
+            $file .= ".pm";
+            my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC;
+
+            my $want = $req_hash->{$phase}{$type}{$mod};
+            $want = "undef" unless defined $want;
+            $want = "any" if !$want && $want == 0;
+
+            my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required";
+
+            if ($prefix) {
+                my $have = MM->parse_version( File::Spec->catfile($prefix, $file) );
+                $have = "undef" unless defined $have;
+                push @reports, [$mod, $want, $have];
+
+                if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) {
+                    if ( $have !~ /\A$lax_version_re\z/ ) {
+                        push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)";
+                    }
+                    elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) {
+                        push @dep_errors, "$mod version '$have' is not in required range '$want'";
+                    }
+                }
+            }
+            else {
+                push @reports, [$mod, $want, "missing"];
+
+                if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) {
+                    push @dep_errors, "$mod is not installed ($req_string)";
+                }
+            }
         }
-      }
-    }
 
-  }
-  else {
-    push @reports, ["missing", $mod];
+        if ( @reports ) {
+            push @full_reports, "=== $title ===\n\n";
+
+            my $ml = _max( map { length $_->[0] } @reports );
+            my $wl = _max( map { length $_->[1] } @reports );
+            my $hl = _max( map { length $_->[2] } @reports );
+            splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl];
 
-    if ( 1 && $all_requires ) {
-      my $req = $req_hash->{$mod};
-      if ( defined $req && length $req ) {
-        push @dep_errors, "$mod is not installed (version '$req' required)";
-      }
+            push @full_reports, map { sprintf("    %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports;
+            push @full_reports, "\n";
+        }
     }
-  }
 }
 
-if ( @reports ) {
-  my $vl = max map { length $_->[0] } @reports;
-  my $ml = max map { length $_->[1] } @reports;
-  splice @reports, 1, 0, ["-" x $vl, "-" x $ml];
-  diag "\nVersions for all modules listed in $source (including optional ones):\n",
-    map {sprintf("  %*s %*s\n",$vl,$_->[0],-$ml,$_->[1])} @reports;
+if ( @full_reports ) {
+    diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports;
 }
 
 if ( @dep_errors ) {
-  diag join("\n",
-    "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n",
-    "The following REQUIRED prerequisites were not satisfied:\n",
-    @dep_errors,
-    "\n"
-  );
+    diag join("\n",
+        "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n",
+        "The following REQUIRED prerequisites were not satisfied:\n",
+        @dep_errors,
+        "\n"
+    );
 }
 
 pass;
 
-# vim: ts=2 sts=2 sw=2 et:
+# vim: ts=4 sts=4 sw=4 et:
@@ -1,6 +1,6 @@
 use strict;
 
-use Test::Builder::Tester tests  => 12;
+use Test::Builder::Tester tests  => 14;
 use Test::Number::Delta relative => 1e-2;
 
 #--------------------------------------------------------------------------#
@@ -19,6 +19,12 @@ test_diag("-50.00 and -49.40 are not equal to within 0.5");
 delta_ok( -50, -49.4, "foo" );
 test_test("delta_ok fail works");
 
+test_out("not ok 1 - foo");
+test_fail(+2);
+test_diag("At [0]: -50.00 and -49.40 are not equal to within 0.5");
+delta_ok( [-50], [-49.4], "foo" );
+test_test("delta_ok fail works");
+
 test_out("ok 1 - foo");
 delta_ok( 10e-5, 9.91e-5, "foo" );
 test_test("delta_ok works");
@@ -41,16 +47,22 @@ test_test("delta_ok works");
 
 test_out("not ok 1 - foo");
 test_fail(+2);
-test_diag("Arguments are equal to within 0.00001");
+test_diag("Arguments are equal to within relative tolerance 0.01");
 delta_not_ok( 1e-3, 9.91e-4, "foo" );
 test_test("delta_not_ok fail works");
 
 test_out("not ok 1 - foo");
 test_fail(+2);
-test_diag("Arguments are equal to within 0.5");
+test_diag("Arguments are equal to within relative tolerance 0.01");
 delta_not_ok( -50, -49.6, "foo" );
 test_test("delta_no_ok fail works");
 
+test_out("not ok 1 - foo");
+test_fail(+2);
+test_diag("Arguments are equal to within relative tolerance 0.01");
+delta_not_ok( [-50], [-49.6], "foo" );
+test_test("delta_no_ok fail works");
+
 test_out("ok 1 - foo");
 delta_not_ok( 10e-5, 9.89e-5, "foo" );
 test_test("delta_not_ok works");
@@ -41,13 +41,13 @@ test_test("delta_ok works");
 
 test_out("not ok 1 - foo");
 test_fail(+2);
-test_diag("Arguments are equal to within 0.00001");
+test_diag("Arguments are equal to within relative tolerance 0.01");
 delta_not_ok( 1e-3, 9.91e-4, "foo" );
 test_test("delta_not_ok fail works");
 
 test_out("not ok 1 - foo");
 test_fail(+2);
-test_diag("Arguments are equal to within 0.5");
+test_diag("Arguments are equal to within relative tolerance 0.01");
 delta_not_ok( -50, -49.6, "foo" );
 test_test("delta_no_ok fail works");
 
@@ -1,11 +1,12 @@
+use 5.006;
 use strict;
 use warnings;
 
-# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.037
-
-use Test::More  tests => 1 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.051
 
+use Test::More;
 
+plan tests => 1 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
 
 my @module_files = (
     'Test/Number/Delta.pm'
@@ -24,11 +25,12 @@ use File::Spec;
 use IPC::Open3;
 use IO::Handle;
 
+open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";
+
 my @warnings;
 for my $lib (@module_files)
 {
     # see L<perlfaq8/How can I capture STDERR from an external command?>
-    open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";
     my $stderr = IO::Handle->new;
 
     my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]");
@@ -46,6 +48,7 @@ for my $lib (@module_files)
 
 
 
-is(scalar(@warnings), 0, 'no warnings found') if $ENV{AUTHOR_TESTING};
+is(scalar(@warnings), 0, 'no warnings found')
+    or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING};
 
 
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 use Test::More;
 
-# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.006001
+# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.006008
 use Test::Spelling 0.12;
 use Pod::Wordlist;
 
@@ -1,7 +1,6 @@
 #!perl
+# This file was automatically generated by Dist::Zilla::Plugin::MetaTests.
 
-use Test::More;
+use Test::CPAN::Meta;
 
-eval "use Test::CPAN::Meta";
-plan skip_all => "Test::CPAN::Meta required for testing META.yml" if $@;
 meta_yaml_ok();
@@ -1,13 +1,7 @@
 #!perl
+# This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests.
 
-use Test::More;
-
-eval "use Test::Pod::Coverage 1.08";
-plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage"
-  if $@;
-
-eval "use Pod::Coverage::TrustPod";
-plan skip_all => "Pod::Coverage::TrustPod required for testing POD coverage"
-  if $@;
+use Test::Pod::Coverage 1.08;
+use Pod::Coverage::TrustPod;
 
 all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' });
@@ -1,7 +1,6 @@
 #!perl
+# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests.
 use Test::More;
-
-eval "use Test::Pod 1.41";
-plan skip_all => "Test::Pod 1.41 required for testing POD" if $@;
+use Test::Pod 1.41;
 
 all_pod_files_ok();
@@ -2,8 +2,8 @@ use strict;
 use warnings;
 use Test::More;
 
-# generated by Dist::Zilla::Plugin::Test::Version 0.002004
-BEGIN { eval "use Test::Version; 1;" or die $@; }
+# generated by Dist::Zilla::Plugin::Test::Version 0.003001
+use Test::Version;
 
 my @imports = ( 'version_all_ok' );