Algorithm-CurveFit-Simple

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for Algorithm::CurveFit::Simple

1.03      2018-03-21
	- Fixed documentation .. was referring to fit() as try() throughout, oops.

1.02      2018-02-05
	- Switched unit test t/03-init-parameters.t from using JSON::PP to is_deeply() to avoid Win32 formatting bug.

1.01      2018-01-31
        - Fixed docs

1.00      2018-01-31
        - Initial release

META.json  view on Meta::CPAN

      "configure" : {
         "requires" : {
            "ExtUtils::MakeMaker" : "0",
            "perl" : "5.010"
         }
      },
      "runtime" : {
         "requires" : {
            "Algorithm::CurveFit" : "0",
            "Exporter" : "0",
            "JSON::PP" : "0",
            "Time::HiRes" : "0",
            "lib" : "0",
            "perl" : "5.010",
            "strict" : "0",
            "warnings" : "0"
         }
      },
      "test" : {
         "requires" : {
            "Test::Most" : "0",

META.yml  view on Meta::CPAN

dynamic_config: 0
generated_by: 'Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.150005'
license: perl
meta-spec:
  url: http://module-build.sourceforge.net/META-spec-v1.4.html
  version: '1.4'
name: Algorithm-CurveFit-Simple
requires:
  Algorithm::CurveFit: '0'
  Exporter: '0'
  JSON::PP: '0'
  Time::HiRes: '0'
  lib: '0'
  perl: '5.010'
  strict: '0'
  warnings: '0'
version: '1.03'

Makefile.PL  view on Meta::CPAN

  },
  "DISTNAME" => "Algorithm-CurveFit-Simple",
  "EXE_FILES" => [
    "bin/curvefit"
  ],
  "LICENSE" => "perl",
  "NAME" => "Algorithm::CurveFit::Simple",
  "PREREQ_PM" => {
    "Algorithm::CurveFit" => 0,
    "Exporter" => 0,
    "JSON::PP" => 0,
    "Time::HiRes" => 0,
    "lib" => 0,
    "strict" => 0,
    "warnings" => 0
  },
  "TEST_REQUIRES" => {
    "Test::Most" => 0
  },
  "VERSION" => "1.03",
  "test" => {
    "TESTS" => "t/*.t"
  }
);


my %FallbackPrereqs = (
  "Algorithm::CurveFit" => 0,
  "Exporter" => 0,
  "JSON::PP" => 0,
  "Test::Most" => 0,
  "Time::HiRes" => 0,
  "lib" => 0,
  "strict" => 0,
  "warnings" => 0
);


unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
  delete $WriteMakefileArgs{TEST_REQUIRES};

bin/curvefit  view on Meta::CPAN

#!/usr/bin/perl
# Copyright (C) 2018 TTK Ciar
# Available for unlimited distribution and use.
# The copyright is just so someone else cannot claim ownership and sue me for use of my own code.

our $VERSION = '1.03'; # VERSION 1.02

use strict;
use warnings;
use JSON::PP;
use lib "./lib";
use Algorithm::CurveFit::Simple qw(fit);

my @DOCS;
my %OPT = (v => 1);
foreach my $arg (@ARGV) {
    if    ($arg =~ /^\-+(.+?)\=(.*)/) { $OPT{$1} = $2; }
    elsif ($arg =~ /^\-+(v+)$/      ) { $OPT{v}  = length($1) + 1; }
    elsif ($arg =~ /^\-+q$/         ) { $OPT{v}  = 0;  }
    elsif ($arg =~ /^\-+quiet$/     ) { $OPT{v}  = 0;  }

bin/curvefit  view on Meta::CPAN


    my (@xdata, @ydata);
    while(defined(my $datum = <STDIN>)) {
        next unless($datum =~ /^\s*([\-+]?[\d\.]+)[\t,]([\-+]?[\d\.]+)/);
        push @xdata, $1;
        push @ydata, $2;
    }

    my ($max_dev, $avg_dev, $src) = fit(xdata => \@xdata, ydata => \@ydata, %OPT);
    print STDERR "$max_dev\n$avg_dev\n" if (opt('v'));
    print STDERR JSON::PP::encode_json(\%Algorithm::CurveFit::Simple::STATS_H)."\n" if (opt('d') || opt('debug') || opt('profile'));
    print "$src\n";
    return 0;
}

sub opt {
    my ($name, $default_value, $alt_hr) = @_;
    return def($OPT{$name}, $alt_hr->{$name}, $default_value);
}

sub def {
    foreach my $v (@_) { return $v if (defined($v)); }
    return undef;
}

sub logger {
    return if (opt('no-log') || opt('log',1) == 0);
    my $log_ar = [localtime(), Time::HiRes::time(), $$, @_];
    my $log_rec = JSON::to_json($log_ar, {ascii => 1, space_after => 1, canonical => 1})."\n";
    print STDERR $log_rec if (opt('show-log'));
    print STDOUT $log_rec if (opt('show-log-to-stdout'));
    File::Valet::ap_f(opt('logfile',"/home/ttk/$PROJECT_NAME.log"), $log_rec) unless(opt('no-logfile'));
    return;
}

sub usage {
    print <<USAGE;
Usage: $0 [options] < data
Input must be x,y data pairs, one pair per line, separated by a comma or tab.

cpanfile  view on Meta::CPAN

requires "Algorithm::CurveFit" => "0";
requires "Exporter" => "0";
requires "JSON::PP" => "0";
requires "Time::HiRes" => "0";
requires "lib" => "0";
requires "perl" => "5.010";
requires "strict" => "0";
requires "warnings" => "0";

on 'test' => sub {
  requires "Test::Most" => "0";
  requires "perl" => "5.010";
};

dist.ini  view on Meta::CPAN

copyright_year   = 2018

[@Basic]
[PruneFiles]
match = ^cover_db

[MinimumPerl]

[AutoPrereqs]
[OurPkgVersion]
[MetaJSON]
[CPANFile]

[Run::BeforeBuild]
run = rm -f Makefile.PL

[Run::AfterBuild]
run = cp %d/Makefile.PL .

[Clean]

lib/Algorithm/CurveFit/Simple.pm  view on Meta::CPAN

package Algorithm::CurveFit::Simple;

# ABSTRACT: Convenience wrapper around Algorithm::CurveFit.

our $VERSION = '1.03'; # VERSION 1.03

use strict;
use warnings;
use Algorithm::CurveFit;
use Time::HiRes;
use JSON::PP;

our %STATS_H;  # side-products of fit() stored here for profiling purposes

BEGIN {
    require Exporter;
    our $VERSION = '1.03';
    our @ISA = qw(Exporter);
    our @EXPORT_OK = qw(fit %STATS_H);
}

t/00-fit.t  view on Meta::CPAN

#!/bin/env perl
use strict;
use warnings;
use Test::Most;
use Time::HiRes;
use JSON::PP;

use lib "./lib";
use Algorithm::CurveFit::Simple qw(fit %STATS_H);

# Pass an argument for profiling purposes, will also dump source code string and statistics
my $N_TERMS = int($ARGV[0] // 0) || '3';
my $LANG    = $ARGV[1] // 'perl';

my $tm0 = Time::HiRes::time();
my ($max_dev, $avg_dev, $src) = eval { fit(terms => $N_TERMS, xydata => [[1, 3], [2, 7], [3, 11], [4, 19], [5, 35], [6, 54], [7, 69], [8, 81], [9, 90], [10, 96]], impl_lang => $LANG); };
print "# exception: $@\n" if ($@);
my $tm_elapsed = Time::HiRes::time() - $tm0;

ok !$@, "no thrown exceptions";
ok $tm_elapsed // 0 <= 4.0, "time elapsed is within expectations";
ok $max_dev    // 0 <= 1.4, "maximum deviation is within expectations";
ok $avg_dev    // 0 <= 1.1, "average deviation is within expectations";

if ($ARGV[0]) {
    print "$src\n";
    print JSON::PP::encode_json([$max_dev, $avg_dev, \%STATS_H])."\n";
}

done_testing();
exit(0);

t/01-init-formula.t  view on Meta::CPAN

#!/bin/env perl
use strict;
use warnings;
use Test::Most;
use JSON::PP;

use lib "./lib";
use Algorithm::CurveFit::Simple qw(%STATS_H);

my $f = eval { Algorithm::CurveFit::Simple::_init_formula(); };
print "# exception: $@\n" if ($@);

ok !$@, "default - no thrown exceptions";
ok defined($f), "default - returned a defined value";
$f //= '';

t/01-init-formula.t  view on Meta::CPAN

    $formula = $f if ($i == 3);
    ok !$@, "with $i terms - no thrown exceptions";
    ok defined($f), "with $i terms - returned a defined value";
    $f //= '';
    is ref($f), '', "with $i terms - returned string";
    ok $f =~ /^k (\+ \w\s?\*\s?x\^?\d*\s*){$i}$/, "with $i terms - formula is well-formed" if($f);
}

if ($ARGV[0]) {
    print "formula=$formula\n";
    print JSON::PP::encode_json(\%STATS_H)."\n";
}

done_testing();
exit(0);

t/02-init-data.t  view on Meta::CPAN

#!/bin/env perl
use strict;
use warnings;
use Test::Most;
use JSON::PP;

use lib "./lib";
use Algorithm::CurveFit::Simple;

my ($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(); };
is $@, "must provide at least xydata or both xdata and ydata\n", "exception thrown for no parameters";

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xdata => [1, 2, 3]); };
is $@, "must provide at least xydata or both xdata and ydata\n", "exception thrown for lacking ydata";

t/02-init-data.t  view on Meta::CPAN

is $@, "must have more than one data-point\n", "exception thrown for insufficient data";

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xdata => [1, 2], ydata => [1]); };
is $@, "xdata and ydata must have the same number of elements\n", "exception thrown for extraneous xdata";

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xdata => [1], ydata => [1, 2]); };
is $@, "xdata and ydata must have the same number of elements\n", "exception thrown for extraneous ydata";

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xdata => [1, 2], ydata => [3, 4]); };
ok !$@, "no exceptions when passed xdata, ydata";
is JSON::PP::encode_json($x), '[1,2]', 'xdata returned as xdata';
is JSON::PP::encode_json($y), '[3,4]', 'ydata returned as ydata';

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xdata => [1, 2], ydata => [3, 4], inv => 1); };
ok !$@, 'no exceptions when passed xdata, ydata with inverted mode';
is JSON::PP::encode_json($y), '[1,2]', 'xdata returned as ydata with inverted mode';
is JSON::PP::encode_json($x), '[3,4]', 'ydata returned as xdata with inverted mode';

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xydata => [[1], [3]]); };
is $@, "pairwise xydata must have two data points per element\n", 'exception thrown for short xydata';

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xydata => [[1, 2], [3, 4], [5, 6]]); };
ok !$@, 'no exceptions when passed well-formed xydata';
# print "$@\n";
# print JSON::PP::encode_json(\%Algorithm::CurveFit::Simple::STATS_H)."\n";
is JSON::PP::encode_json($x), '[1,3,5]', 'xdata returned as xdata from xydata';
is JSON::PP::encode_json($y), '[2,4,6]', 'ydata returned as ydata from xydata';

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xydata => [[1, 2, 3, 4], [3, 4, 5, 6]]); };
ok !$@, 'no exceptions when passed xdata, ydata';
is JSON::PP::encode_json($x), '[1,2,3,4]', 'xdata returned as xdata from long xydata';
is JSON::PP::encode_json($y), '[3,4,5,6]', 'ydata returned as ydata from long xydata';

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xydata => [[1, 2, 3, 4], [3, 4, 5, 6]], inv => 1); };
ok !$@, 'no exceptions when passed xdata, ydata';
is JSON::PP::encode_json($x), '[3,4,5,6]', 'xdata returned as xdata from long xydata with inverted mode';
is JSON::PP::encode_json($y), '[1,2,3,4]', 'ydata returned as ydata from long xydata with inverted mode';

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xydata => [[1, 2], [3, 4], [5, 6], [7, 8]]); };
ok !$@, 'no exceptions when passed xydata as paired points';
is JSON::PP::encode_json($x), '[1,3,5,7]', 'xdata returned as xdata from paired-point xydata';
is JSON::PP::encode_json($y), '[2,4,6,8]', 'ydata returned as ydata from paired-point xydata';

($x, $y) = eval { Algorithm::CurveFit::Simple::_init_data(xydata => [[1, 2], [3, 4], [5, 6], [7, 8]], inv => 1); };
ok !$@, 'no exceptions when passed xydata as paired points with inverted mode';
is JSON::PP::encode_json($y), '[1,3,5,7]', 'xdata returned as ydata from paired-point xydata, inverted';
is JSON::PP::encode_json($x), '[2,4,6,8]', 'ydata returned as xdata from paired-point xydata, inverted';

if ($ARGV[0]) {
    print JSON::PP::encode_json(\%Algorithm::CurveFit::Simple::STATS_H)."\n";
}

done_testing();
exit(0);

t/03-init-parameters.t  view on Meta::CPAN

#!/bin/env perl
use strict;
use warnings;
use Test::Most;
use JSON::PP;

use lib "./lib";
use Algorithm::CurveFit::Simple;

my $p = eval { Algorithm::CurveFit::Simple::_init_parameters([3, 5, 7, 9], [1, 2, 3, 4]); };
is_deeply $p, [["k", 2.5, 1e-07], ["a", 0.5, 1e-07], ["b", 0.5, 1e-07], ["c", 0.5, 1e-07]], 'default parameters';

$p = eval { Algorithm::CurveFit::Simple::_init_parameters([3, 5, 7, 9], [1, 2, 3, 4], terms => 2); };
is_deeply $p, [["k", 2.5, 1e-07], ["a", 0.5, 1e-07], ["b", 0.5, 1e-07]], 'explicit term parameters';

if ($ARGV[0]) {
    print JSON::PP::encode_json(\%Algorithm::CurveFit::Simple::STATS_H)."\n";
}

done_testing();
exit(0);

t/04-implement-formula.t  view on Meta::CPAN

#!/bin/env perl
use strict;
use warnings;
use Test::Most;
use JSON::PP;

use lib "./lib";
use Algorithm::CurveFit::Simple;

my $parar = [["k", 10, 1], ["a", 2, 1], ["b", 3, 1], ["c", 4, 1]];
my $xdata = [8, 3, 5, 11, 9, 7, 4];

my $s = eval { Algorithm::CurveFit::Simple::_implement_formula($parar, "", "x2y", $xdata, {}); };
ok defined($s), "implementation default throws no exceptions";
ok $s =~ /^sub x2y /, "implementation default is perl";

t/04-implement-formula.t  view on Meta::CPAN

ok $s =~ /return -1.0/, "implementation C with bounds check is limited";
ok $s !~ /y = round/, "implementation C with bounds check without round result returns precision result";
print $Algorithm::CurveFit::Simple::STATS_H{impl_source} . "\n" if ($ARGV[0]);

$s = eval { Algorithm::CurveFit::Simple::_implement_formula($parar, "c", "x2y", $xdata, {round_result => 1}); };
ok $s !~ /return -1.0/, "implementation C without bounds check with round result is permissive";
ok $s =~ /y = round/, "implementation C without bounds check with round result returns rounded result";
print $Algorithm::CurveFit::Simple::STATS_H{impl_source} . "\n" if ($ARGV[0]);

if ($ARGV[0]) {
    print JSON::PP::encode_json(\%Algorithm::CurveFit::Simple::STATS_H) . "\n";
}

done_testing();
exit(0);



( run in 1.161 second using v1.01-cache-2.11-cpan-140bd7fdf52 )