New Controllers added. Added Charts
This commit is contained in:
168
Laravel/vendor/jlawrence/eos/README.md
vendored
Normal file
168
Laravel/vendor/jlawrence/eos/README.md
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
# EOS
|
||||
|
||||
[](https://travis-ci.org/jlawrence11/eos)
|
||||
[](https://packagist.org/packages/jlawrence/eos)
|
||||
[](https://packagist.org/packages/jlawrence/eos)
|
||||
[](https://packagist.org/packages/jlawrence/eos)
|
||||
[](https://packagist.org/packages/jlawrence/eos)
|
||||
[](https://codeclimate.com/github/jlawrence11/eos)
|
||||
[](https://codeclimate.com/github/jlawrence11/eos)
|
||||
|
||||
## Installation
|
||||
|
||||
Install EOS with [Composer](https://getcomposer.org/)
|
||||
|
||||
Add the dependency:
|
||||
|
||||
```json
|
||||
"require": {
|
||||
"jlawrence/eos": "3.*"
|
||||
}
|
||||
```
|
||||
|
||||
Run `composer update` and you're done.
|
||||
|
||||
## Equation Operating System
|
||||
|
||||
### jlawrence\eos\
|
||||
|
||||
This class makes it incredibly easy to use and parse/solve equations in
|
||||
your own applications. __NOTE__ ALL of the functions within
|
||||
these classes are static. It is also important to note that these
|
||||
classes throw exceptions if running in to errors, please read the beginning
|
||||
of the `Math.php` file for the defines of the exceptions thrown. Exceptions
|
||||
includes a descriptive message of the error encountered and within `Parser` will
|
||||
also typically include the full equation used.
|
||||
|
||||
#### Parser
|
||||
|
||||
This class has one important function, `Parser::solve()` which does all the legwork,
|
||||
so we'll start there and end with examples.
|
||||
|
||||
use jlawrence\eos\Parser;
|
||||
|
||||
##### solve($infix, $variables)
|
||||
|
||||
To use this function:
|
||||
|
||||
$value = Parser::solve($eq, $vars);
|
||||
|
||||
###### _$infix_
|
||||
|
||||
Is simply a standard equation with variable support.
|
||||
|
||||
Example Equations:
|
||||
|
||||
2(4x)
|
||||
5+((1+2)*4)+3
|
||||
5+4(1+2)+3
|
||||
10*sin(x)
|
||||
10*cos(x)
|
||||
|
||||
The parser has good implied multiplication.
|
||||
|
||||
###### _$variables_
|
||||
|
||||
The variables are fairly simple to understand. If it contains a scalar (ie
|
||||
a non-array value) _every_ variable within the equation will be replaced with
|
||||
that number. If it contains an array, there will be a by-variable replacement -
|
||||
note that the array MUST be in the format of `'variable' => value`
|
||||
Such as:
|
||||
|
||||
array(
|
||||
'x' => 2,
|
||||
'y' => 3
|
||||
);
|
||||
|
||||
Given the equation:
|
||||
|
||||
5x^y
|
||||
|
||||
If this is called by:
|
||||
|
||||
Parser::solveIF('5x^y', 2);
|
||||
|
||||
It will equal '20', as every variable is replaced by 2. However, if called like:
|
||||
|
||||
Parser::solveIF('5x^y', array(
|
||||
'x' => 2,
|
||||
'y' => 3));
|
||||
|
||||
You will get the result of '40' as it would equate to `5*2^3`, as expected.
|
||||
|
||||
#### jlawrence\eos\Graph
|
||||
|
||||
To use:
|
||||
|
||||
use jlawrence\eos\Graph;
|
||||
|
||||
This is the fun class that can create graphs.
|
||||
The image will default to 640x480, to initialize a different size use:
|
||||
|
||||
Graph::init($width, $height);
|
||||
|
||||
The `$width` and `$height` are the values used for the image size.
|
||||
|
||||
##### graph($eq, $xLow, $xHigh, [$xStep, $xyGrid, $yGuess, ...])
|
||||
|
||||
This method will generate the graph for the equation (`$eq`) with a min and max
|
||||
`x` range that it will parse through. All Variables explained:
|
||||
|
||||
* `$eq`
|
||||
The Standard Equation to use. _Must_ have a variable in it. (ie `x`)
|
||||
* `$xLow`
|
||||
The starting point for the calculations - the left side of the graph.
|
||||
* `$xHigh`
|
||||
The last point calculated for the variable - the right side of the graph.
|
||||
* `$xStep`
|
||||
Stepping point for the variable. Set to null/false to use the smart xStep feature within the graph class.
|
||||
* `$xyGrid = false`
|
||||
Show `x/y` gridlines on the graph. Defaults to false. Each grid line is set at an integer, with a max of 30 lines, so it will calculate the stepping for it. When the grid is show, the lines are labeled along the top and left side of the image.
|
||||
* `$yGuess = true`
|
||||
Guess the Lower and Upper `y-bounds` (The bottom and top of the image
|
||||
respectively.) This will set the the bounds to the lowest `y` value
|
||||
encountered for the `$yLow`, and the largest `y` value for `$yHigh`.
|
||||
* `$yLow = null`
|
||||
Lower bound for `y`. Will be reset if a lower value for `y` is found if `$yGuess` is true.
|
||||
* `$yHigh = null`
|
||||
Upper bound for `y`. Will be reset if a larger `y` value is found if `$yGuess` is true.
|
||||
|
||||
If you don't want the axis' labeled with their numbers, you can turn off the default behavior with:
|
||||
|
||||
Graph::$labelAxis = false;
|
||||
|
||||
TODO:
|
||||
|
||||
* Allow user-defined colors for all aspects of the graph.
|
||||
|
||||
To set up a graph with a `21x21` window (ie `-10 to 10`) for the equation
|
||||
`sin(x)` and output as PNG, would use as:
|
||||
|
||||
Graph::graph('sin(x)', -10, 10, 0.01, true, false, -10, 10);
|
||||
Graph::outPNG();
|
||||
|
||||
It would look like:
|
||||

|
||||
|
||||
## Development
|
||||
|
||||
### Testing
|
||||
|
||||
Run the unit tests by first installing phpunit with (from the repository root)
|
||||
|
||||
```
|
||||
composer update
|
||||
```
|
||||
|
||||
Then run the tests with
|
||||
|
||||
```
|
||||
phpunit
|
||||
```
|
||||
---
|
||||
|
||||
When creating classes for adding functions to the package, make sure to call
|
||||
`Parser::solveIF()` instead of `Parser::solve()` so that the class retains
|
||||
the full original equation used by the user.
|
||||
|
||||
---
|
22
Laravel/vendor/jlawrence/eos/composer.json
vendored
Normal file
22
Laravel/vendor/jlawrence/eos/composer.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "jlawrence/eos",
|
||||
"description": "Parse and solve math equations without using 'eval()'.",
|
||||
"license": "LGPL-2.1+",
|
||||
"keywords": ["EOS","equations","math","solve"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jon Lawrence",
|
||||
"email": "jon@jon-lawrence.com"
|
||||
}
|
||||
],
|
||||
"require": {},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*",
|
||||
"codeclimate/php-test-reporter": "dev-master"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"jlawrence\\eos\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
86
Laravel/vendor/jlawrence/eos/src/AdvancedFunctions.php
vendored
Normal file
86
Laravel/vendor/jlawrence/eos/src/AdvancedFunctions.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by: Jon Lawrence on 2015-07-13 8:42 AM
|
||||
*/
|
||||
|
||||
namespace jlawrence\eos;
|
||||
|
||||
|
||||
class AdvancedFunctions
|
||||
{
|
||||
|
||||
/**
|
||||
* Create a list for the parser of 'expressiveFunction' => 'class::function'
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function map()
|
||||
{
|
||||
$ret = array(
|
||||
'sum' => __NAMESPACE__ .'\AdvancedFunctions::sum',
|
||||
'log' => __NAMESPACE__ .'\AdvancedFunctions::log'
|
||||
);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Summation function
|
||||
*
|
||||
* Will take an equation and run it through a summation algorithm. All parts
|
||||
* of the input can be in equation form, so the start and stops can have
|
||||
* equations to determine what they should be using the globally inputted
|
||||
* variables from the user.
|
||||
*
|
||||
* @param string $input String in the form of "equation, start, stop"
|
||||
* @param array $vars Array of variables used for solving the current equation.
|
||||
* @return float The summation of the equation
|
||||
*/
|
||||
public static function sum($input, $vars)
|
||||
{
|
||||
//remove whitespace
|
||||
$input = preg_replace("/\s/", "", $input);
|
||||
//split in to parts
|
||||
list($eq, $start, $stop) = explode(",", $input);
|
||||
$ret = 0;
|
||||
//make sure there's a variable, or return equation as-is
|
||||
if((Parser::solveIF($eq,0)) == preg_replace("/[\(\)]/", "", $eq)) {
|
||||
return $eq;
|
||||
}
|
||||
$start = Parser::solveIF($start, $vars);
|
||||
$stop = Parser::solveIF($stop, $vars);
|
||||
for($i=$start; $i <= $stop; $i++) {
|
||||
$ret += Parser::solveIF($eq, $i);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log function for all non-natural logs. Defaults to base 10
|
||||
*
|
||||
* @param $input
|
||||
* @param array $vars Variable replacement
|
||||
* @return float
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function log($input, $vars)
|
||||
{
|
||||
$base = 10;
|
||||
if(stripos($input, ",")) {
|
||||
list($eq, $base) = explode(",", $input);
|
||||
} else {
|
||||
$eq = $input;
|
||||
}
|
||||
//Make sure no functions or operators are hidden inside
|
||||
$sc = Parser::solveIF($eq, $vars);
|
||||
if(10 != $base) {
|
||||
$base = Parser::solveIF($base, $vars);
|
||||
}
|
||||
$ans = log($sc, $base);
|
||||
if(is_nan($ans) || is_infinite($ans)) {
|
||||
throw new \Exception("Result of 'log({$eq}, {$base}) = {$ans}' is either infinite or a non-number in ". Parser::$inFix, Math::E_NAN);
|
||||
}
|
||||
return $ans;
|
||||
}
|
||||
}
|
281
Laravel/vendor/jlawrence/eos/src/Graph.php
vendored
Normal file
281
Laravel/vendor/jlawrence/eos/src/Graph.php
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
|
||||
namespace jlawrence\eos;
|
||||
|
||||
// fun class that requires the GD libraries to give visual output to the user
|
||||
|
||||
/**
|
||||
* Equation Graph
|
||||
*
|
||||
* Fun class that requires the GD libraries to give visual output of an
|
||||
* equation to the user. Extends the Parser class.
|
||||
*
|
||||
* @author Jon Lawrence <jlawrence11@gmail.com>
|
||||
* @copyright Copyright ©2005-2013 Jon Lawrence
|
||||
* @license http://opensource.org/licenses/LGPL-2.1 LGPL 2.1 License
|
||||
* @package Math
|
||||
* @subpackage EOS
|
||||
* @version 3.x
|
||||
*/
|
||||
class Graph
|
||||
{
|
||||
private static $width = 640;
|
||||
private static $height = 480;
|
||||
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private static $image;
|
||||
|
||||
public static $labelAxis = true;
|
||||
public static $backgroundColor = array(255, 255, 255);
|
||||
public static $gridColor = array(150, 150, 150);
|
||||
public static $axisColor = array(0, 0, 0);
|
||||
public static $lineColor = array(0, 0, 0);
|
||||
|
||||
/**
|
||||
* Initializer
|
||||
*
|
||||
* Sets up the Graph class with an image width and height defaults to
|
||||
* 640x480
|
||||
*
|
||||
* @param int $width Image width
|
||||
* @param int $height Image height
|
||||
*/
|
||||
public static function init($width = 640, $height = 480)
|
||||
{
|
||||
// default width and height equal to that of a poor monitor (in early 2000s)
|
||||
self::$width = $width;
|
||||
self::$height = $height;
|
||||
|
||||
// initialize main class
|
||||
Parser::init();
|
||||
//can't really mess this up, return true
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create GD Graph Image
|
||||
*
|
||||
* Creates a GD image based on the equation given with the parameters that are set
|
||||
*
|
||||
* @param string $eq Equation to use. Needs variable in equation to create graph, all variables are interpreted as 'x'
|
||||
* @param integer $xLow Lower x-bound for graph
|
||||
* @param integer $xHigh Upper x-bound for graph
|
||||
* @param float $xStep Stepping points while solving, the lower, the better precision. Slow if lower than .01
|
||||
* @param bool $xyGrid Draw grid-lines?
|
||||
* @param bool $yGuess Guess the upper/lower yBounds?
|
||||
* @param int $yLow Lower y-bound
|
||||
* @param int $yHigh Upper y-bound
|
||||
* @return null
|
||||
*/
|
||||
public static function graph($eq, $xLow, $xHigh, $xStep = null, $xyGrid = false, $yGuess = true, $yLow = null, $yHigh = null)
|
||||
{
|
||||
//create our image and allocate the two colors
|
||||
$img = ImageCreate(self::$width, self::$height);
|
||||
//The following noinspection needed because the first color allocated is the background, but not used for anything else.
|
||||
/** @noinspection PhpUnusedLocalVariableInspection */
|
||||
$bgColor = ImageColorAllocate($img, self::$backgroundColor[0], self::$backgroundColor[1], self::$backgroundColor[2]);
|
||||
$aColor = ImageColorAllocate($img, self::$axisColor[0], self::$axisColor[1], self::$axisColor[2]);
|
||||
$lColor = ImageColorAllocate($img, self::$lineColor[0], self::$lineColor[1], self::$lineColor[2]);
|
||||
$gColor = ImageColorAllocate($img, self::$gridColor[0], self::$gridColor[1], self::$gridColor[2]);
|
||||
//$black = ImageColorAllocate($img, 0, 0, 0);
|
||||
//$grey = ImageColorAllocate($img, 150, 150, 150);
|
||||
//$darkGrey = ImageColorAllocate($img, 50, 50, 50);
|
||||
if ($xLow > $xHigh)
|
||||
list($xLow, $xHigh) = array($xHigh, $xLow); //swap function
|
||||
//Smart xStep calc
|
||||
if ($xStep == false) {
|
||||
$xStep = ($xHigh - $xLow) / self::$width;
|
||||
}
|
||||
$xStep = abs($xStep);
|
||||
$hand = null;
|
||||
$xVars = array();
|
||||
//If yGuess is true, make sure yLow and yHigh are not set
|
||||
if ($yGuess) {
|
||||
$yLow = null;
|
||||
$yHigh = null;
|
||||
}
|
||||
//We want to limit the number of lines/ticks/etc so graph remains readable, set max now
|
||||
$xMaxLines = 30;
|
||||
$yMaxLines = 30;
|
||||
//DEVELOPER, UNCOMMENT NEXT LINE IF WANTING TO PREVENT SLOW GRAPHS
|
||||
//$xStep = ($xStep < .01) ? $xStep : 0.01;
|
||||
|
||||
$xScale = self::$width / ($xHigh - $xLow);
|
||||
$counter = 0;
|
||||
// @codeCoverageIgnoreStart
|
||||
if (Math::$DEBUG) {
|
||||
$hand = fopen("Graph.txt", "w");
|
||||
fwrite($hand, "$eq\n");
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
for ($i = $xLow; $i <= $xHigh; $i += $xStep) {
|
||||
$tester = sprintf("%10.3f", $i);
|
||||
if ($tester == "-0.000") $i = 0;
|
||||
$y = Parser::solve($eq, $i);
|
||||
//eval('$y='. str_replace('&x', $i, $eq).";"); /* used to debug my Parser class results */
|
||||
// @codeCoverageIgnoreStart
|
||||
if (Math::$DEBUG) {
|
||||
$tmp1 = sprintf("y(%5.3f) = %10.3f\n", $i, $y);
|
||||
fwrite($hand, $tmp1);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// If developer asked us to find the upper and lower bounds for y...
|
||||
if ($yGuess == true) {
|
||||
$yLow = ($yLow === null || ($y < $yLow)) ? $y : $yLow;
|
||||
$yHigh = ($yHigh === null || $y > $yHigh) ? $y : $yHigh;
|
||||
}
|
||||
$xVars[$counter] = $y;
|
||||
$counter++;
|
||||
}
|
||||
|
||||
|
||||
//Now that we have all the variables stored...find the yScale
|
||||
$yScale = self::$height / (($yHigh) - ($yLow));
|
||||
// @codeCoverageIgnoreStart
|
||||
//Calculate the stepping points for lines now
|
||||
if ($yHigh - $yLow > $yMaxLines) {
|
||||
$yJump = ceil(($yHigh - $yLow) / $yMaxLines);
|
||||
} else {
|
||||
$yJump = 1;
|
||||
}
|
||||
if ($xHigh - $xLow > $xMaxLines) {
|
||||
$xJump = ceil(($xHigh - $xLow) / $xMaxLines);
|
||||
} else {
|
||||
$xJump = 1;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// add 0.01 to each side so that if y is from 1 to 5, the lines at 1 and 5 are seen
|
||||
$yLow -= 0.01;
|
||||
$yHigh += 0.01;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if (Math::$DEBUG) {
|
||||
fwrite($hand, $yLow . " -- " . $yHigh . "\n");
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// if developer wanted a grid on the graph, add it now
|
||||
if ($xyGrid == true) {
|
||||
// @codeCoverageIgnoreStart
|
||||
if (Math::$DEBUG) {
|
||||
fwrite($hand, "Drawing Grid\n");
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
for ($i = ceil($yLow); $i <= floor($yHigh); $i += $yJump) {
|
||||
$i0 = abs($yHigh - $i);
|
||||
ImageLine($img, 0, $i0 * $yScale, self::$width, $i0 * $yScale, $gColor);
|
||||
imagestring($img, 1, 2, $i0 * $yScale + 2, $i, $gColor);
|
||||
}
|
||||
for ($i = ceil($xLow); $i <= floor($xHigh); $i += $xJump) {
|
||||
$i0 = abs($xLow - $i);
|
||||
ImageLine($img, $i0 * $xScale, 0, $i0 * $xScale, self::$height, $gColor);
|
||||
imagestring($img, 1, $i0 * $xScale + 2, 2, $i, $gColor);
|
||||
}
|
||||
}
|
||||
|
||||
//Now that we have the scales, let's see if we can draw an x/y-axis
|
||||
if ($xLow <= 0 && $xHigh >= 0) {
|
||||
//the y-axis is within our range - draw it.
|
||||
$x0 = abs($xLow) * $xScale;
|
||||
ImageLine($img, $x0, 0, $x0, self::$height, $aColor);
|
||||
for ($i = ceil($yLow); $i <= floor($yHigh); $i += $yJump) {
|
||||
$i0 = abs($yHigh - $i);
|
||||
ImageLine($img, $x0 - 3, $i0 * $yScale, $x0 + 3, $i0 * $yScale, $aColor);
|
||||
//If we want the axis labeled... (call in the allies?)
|
||||
if (self::$labelAxis) {
|
||||
imagestring($img, 1, $x0 + 2, $i0 * $yScale + 1, $i, $aColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($yLow <= 0 && $yHigh >= 0) {
|
||||
//the x-axis is within our range - draw it.
|
||||
$y0 = abs($yHigh) * $yScale;
|
||||
ImageLine($img, 0, $y0, self::$width, $y0, $aColor);
|
||||
//Create ticks for y
|
||||
for ($i = ceil($xLow); $i <= floor($xHigh); $i += $xJump) {
|
||||
$i0 = abs($xLow - $i);
|
||||
ImageLine($img, $i0 * $xScale, $y0 - 3, $i0 * $xScale, $y0 + 3, $aColor);
|
||||
//If we want the axis labeled....
|
||||
if (self::$labelAxis) {
|
||||
imagestring($img, 1, $i0 * $xScale + 2, $y0 + 1, $i, $aColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
$counter = 1;
|
||||
|
||||
//now graph it all ;]
|
||||
for ($i = $xLow + $xStep; $i <= $xHigh; $i += $xStep) {
|
||||
$x1 = (abs($xLow - ($i - $xStep))) * $xScale;
|
||||
$y1 = (($xVars[$counter - 1] < $yLow) || ($xVars[$counter - 1] > $yHigh)) ? -1 : (abs($yHigh - $xVars[$counter - 1])) * $yScale;
|
||||
$x2 = (abs($xLow - $i)) * $xScale;
|
||||
$y2 = (($xVars[$counter] < $yLow) || ($xVars[$counter] > $yHigh)) ? -1 : (abs($yHigh - $xVars[$counter])) * $yScale;
|
||||
|
||||
// if any of the y values were found to be off of the y-bounds, don't graph those connecting lines
|
||||
if ($y1 != -1 && $y2 != -1)
|
||||
ImageLine($img, $x1, $y1, $x2, $y2, $lColor);
|
||||
$counter++;
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
if (Math::$DEBUG) {
|
||||
fclose($hand);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
self::$image = $img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends JPG to browser
|
||||
*
|
||||
* Sends a JPG image with proper header to output
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function outJPG()
|
||||
{
|
||||
header("Content-type: image/jpeg");
|
||||
ImageJpeg(self::$image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends PNG to browser
|
||||
*
|
||||
* Sends a PNG image with proper header to output
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function outPNG()
|
||||
{
|
||||
header("Content-type: image/png");
|
||||
ImagePng(self::$image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output GD Image
|
||||
*
|
||||
* Will give the developer the GD resource for the graph that
|
||||
* can be used to store the graph to the FS or other media
|
||||
*
|
||||
* @return Resource GD Image Resource
|
||||
*/
|
||||
public static function getImage()
|
||||
{
|
||||
return self::$image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output GD Image
|
||||
*
|
||||
* Alias for eqGraph::getImage()
|
||||
*
|
||||
* @return Resource GD Image resource
|
||||
*/
|
||||
public static function outGD()
|
||||
{
|
||||
return self::getImage();
|
||||
}
|
||||
}
|
47
Laravel/vendor/jlawrence/eos/src/Math.php
vendored
Normal file
47
Laravel/vendor/jlawrence/eos/src/Math.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by: Jon Lawrence on 2015-07-02 2:49 PM
|
||||
*/
|
||||
|
||||
namespace jlawrence\eos;
|
||||
|
||||
/**
|
||||
* Class Math
|
||||
* @package jlawrence\eos
|
||||
*
|
||||
* Will be a holder for constants, variables, and other things commonly needed by the
|
||||
* rest of the package.
|
||||
*/
|
||||
class Math
|
||||
{
|
||||
/**
|
||||
* No matching open/close pair in equation
|
||||
*/
|
||||
const E_NO_SET = 5500;
|
||||
|
||||
/**
|
||||
* Division by zero
|
||||
*/
|
||||
const E_DIV_ZERO = 5501;
|
||||
|
||||
/**
|
||||
* No equation present
|
||||
*/
|
||||
const E_NO_EQ = 5502;
|
||||
|
||||
/**
|
||||
* No variable replacements available
|
||||
*/
|
||||
const E_NO_VAR = 5503;
|
||||
|
||||
/**
|
||||
* Not A Number (NAN)
|
||||
*/
|
||||
const E_NAN = 5504;
|
||||
|
||||
/**
|
||||
* @var bool Use debug features
|
||||
*/
|
||||
public static $DEBUG = false;
|
||||
|
||||
}
|
656
Laravel/vendor/jlawrence/eos/src/Matrix.php
vendored
Normal file
656
Laravel/vendor/jlawrence/eos/src/Matrix.php
vendored
Normal file
@@ -0,0 +1,656 @@
|
||||
<?php
|
||||
/**
|
||||
* matrix.class.php
|
||||
*
|
||||
* Will set up the defines for error checking as well as provide
|
||||
* the Matrix class for include. As this is made to be modular,
|
||||
* only the class (and possibly helper classes) along with their
|
||||
* defines will be found in this file.
|
||||
* @package Math
|
||||
* @subpackage Matrix
|
||||
*/
|
||||
|
||||
namespace jlawrence\eos;
|
||||
|
||||
/**
|
||||
* Matrix Class
|
||||
*
|
||||
* This class will allow you to create and use Matrices
|
||||
* as well as providing common Matrix operations. It
|
||||
* uses PHP5 for OOP and Error Throwing and is commented
|
||||
* for the PHPDoc Parser for documentation creation.
|
||||
*
|
||||
* @version $Id: matrix.class.php 10 2012-08-06 23:41:36Z jlawrence11 $
|
||||
* @author Jon Lawrence <JLawrence11@gmail.com>
|
||||
* @license http://opensource.org/licenses/LGPL-2.1 LGPL 2.1 License
|
||||
* @copyright Copyright <20>2012, Jon Lawrence
|
||||
* @package Math
|
||||
* @subpackage Matrix
|
||||
*/
|
||||
class Matrix {
|
||||
|
||||
/**
|
||||
* Invalid String input type
|
||||
*/
|
||||
const E_INVALID_INPUT = 5001;
|
||||
|
||||
/**
|
||||
* Matrix needed to be a square matrix for the operation
|
||||
*/
|
||||
const E_NOT_SQUARE = 5002;
|
||||
|
||||
/**
|
||||
* Matrix was undefined
|
||||
*/
|
||||
const E_NO_MATRIX = 5003;
|
||||
|
||||
/**
|
||||
* Matrix had varying column lengths
|
||||
*/
|
||||
const E_INVALID_MATRIX = 5004;
|
||||
|
||||
/**
|
||||
* Matrix operation required rows/cols to be even, they were not
|
||||
*/
|
||||
const E_NOT_EQUAL = 5005;
|
||||
|
||||
/**
|
||||
* Determinate was '0' while preforming another operation
|
||||
*/
|
||||
const E_NO_INVERSE = 5006;
|
||||
|
||||
private $matrix;
|
||||
|
||||
/**
|
||||
* Construct method
|
||||
*
|
||||
* For format of input string, see the see tag below
|
||||
*
|
||||
* @see Matrix::_assign()
|
||||
* @param string $mText Matrix text input
|
||||
*/
|
||||
public function __construct($mText="")
|
||||
{
|
||||
if ($mText) $this->_assign($mText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a matrix based on string input similar to the TI Calculators
|
||||
* input string "[1,2,3;4,5,6;7,8,9]" is the equivalent of the matrix:
|
||||
* <pre>
|
||||
* | 1 2 3 |
|
||||
* | 4 5 6 |
|
||||
* | 7 8 9 |
|
||||
* </pre>
|
||||
*
|
||||
* @param String $mText The matrix in string format to assign to the current object
|
||||
* @return Boolean True if is passes verification after being converted
|
||||
* @throws \Exception If the input text is not in a valid format
|
||||
*/
|
||||
public function _assign($mText)
|
||||
{
|
||||
if(trim($mText)=="")
|
||||
return false;
|
||||
|
||||
$mText = preg_replace("/\s/", "", $mText);
|
||||
if(!preg_match("/^\[(([\-]*[0-9\. ]+[,]{0,1})+[;]{0,1})*\]$/", $mText)) {
|
||||
throw new \Exception("'{$mText}' is not a valid input", Matrix::E_INVALID_INPUT);
|
||||
}
|
||||
$mText = preg_replace("/(\[|\])/", "", $mText);
|
||||
|
||||
$rows = explode(";", $mText);
|
||||
$i=0;$j=0;
|
||||
foreach($rows as $row)
|
||||
{
|
||||
$cols = explode(",", $row);
|
||||
foreach($cols as $value)
|
||||
{
|
||||
$this->matrix[$i][$j] = $value;
|
||||
$j++;
|
||||
}
|
||||
$i++;
|
||||
$j = 0;
|
||||
}
|
||||
|
||||
return $this->_verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function that will verify all the columns have the same
|
||||
* number of items, ensuring it is a valid matrix
|
||||
*
|
||||
* @access private
|
||||
* @param array|bool $mArray
|
||||
* @return bool True if it passes, false if not a valid matrix
|
||||
*/
|
||||
private function _verify($mArray = false)
|
||||
{
|
||||
if(!$mArray) $mArray = $this->matrix;
|
||||
$nSet = false;
|
||||
|
||||
if(is_array($mArray))
|
||||
{
|
||||
foreach($mArray as $row)
|
||||
{
|
||||
$cols = count($row);
|
||||
if($nSet===false) {
|
||||
$nSet = $cols;
|
||||
}
|
||||
if($cols != $nSet) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it a valid matrix?
|
||||
*
|
||||
* Public function to tell the class user whether or not the passed
|
||||
* array is valid, if no array is passed, it will tell the user whether
|
||||
* the matrix of the current instance is valid. Valid is denoted by all
|
||||
* rows have the same number of columns.
|
||||
*
|
||||
* @param array|bool $mArray Array to be used, if not assigned will default to $this->matrix
|
||||
* @return bool True/False depending on if array is a valid matrix
|
||||
*/
|
||||
public function isValid($mArray = false)
|
||||
{
|
||||
if(!$mArray) $mArray = $this->matrix;
|
||||
return $this->_verify($mArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it a square Matrix?
|
||||
*
|
||||
* Will determine whether or not the matrix is valid, and if it
|
||||
* is, will determine if the matrix is a square matrix (n by n).
|
||||
*
|
||||
* @param array|bool $mArray Matrix array, if not assigned will use $this->matrix
|
||||
* @return bool True/False depending on whether or not the matrix is square
|
||||
*/
|
||||
public function isSquare($mArray = false)
|
||||
{
|
||||
if(!$mArray) $mArray = $this->matrix;
|
||||
if(!$this->_verify($mArray)) {
|
||||
return false;
|
||||
}
|
||||
$rows = count($mArray);
|
||||
$cols = count($mArray[0]);
|
||||
return ($rows == $cols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get 'n' from a square (n by n) Matrix
|
||||
*
|
||||
* Will check to see if a matrix is square, if so, will return 'n', which
|
||||
* is the number of rows==columns in the matrix
|
||||
*
|
||||
* @param array|bool $mArray Matrix array, uses $this->matrix if not assigned
|
||||
* @return int The 'n' of a square matrix, or false if not square
|
||||
* @throws \Exception If not a square matrix, throws an exception
|
||||
*/
|
||||
public function _getN($mArray = false)
|
||||
{
|
||||
if(!$mArray) $mArray = $this->matrix;
|
||||
|
||||
if($this->isSquare($mArray)) {
|
||||
return count($mArray);
|
||||
} else {
|
||||
$m = $this->toString($mArray);
|
||||
throw new \Exception("'{$m}' is not a square matrix", Matrix::E_NOT_SQUARE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Identity Matrix
|
||||
*
|
||||
* Creates an Identity Matrix of size 'n'.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Identity_matrix
|
||||
* @param int $n The rows/cols of identity matrix
|
||||
* @param bool $useInternal If true will set $this->matrix
|
||||
* @return Matrix|bool Return an identity matrix if $useInternal is false, otherwise 'true'
|
||||
*/
|
||||
public function createIdentity($n, $useInternal = true)
|
||||
{
|
||||
$mArray = array();
|
||||
for($rows=0;$rows<$n;$rows++) {
|
||||
for($cols=0;$cols<$n;$cols++) {
|
||||
if($rows==$cols) {
|
||||
$mArray[$rows][$cols] = 1;
|
||||
} else {
|
||||
$mArray[$rows][$cols] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($useInternal == true) {
|
||||
$this->matrix = $mArray;
|
||||
return true;
|
||||
} else {
|
||||
$nMatrix = new Matrix($this->toString($mArray));
|
||||
return $nMatrix;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert current Matrix to string format
|
||||
*
|
||||
* Convert an array to the string format used by this class.
|
||||
*
|
||||
* @see Matrix::_assign()
|
||||
* @param array|bool $mArray if not assigned will use this instance's matrix.
|
||||
* @throws \Exception If matrix is not an array
|
||||
* @return string The array broken down in to string format
|
||||
*/
|
||||
public function toString($mArray = false)
|
||||
{
|
||||
if(!$mArray) $mArray = $this->matrix;
|
||||
$rows=array();
|
||||
if(is_array($mArray))
|
||||
{
|
||||
foreach($mArray as $cols){
|
||||
$rows[] = implode(",", $cols);
|
||||
}
|
||||
$retString = sprintf("[%s]", implode($rows, ";"));
|
||||
return $retString;
|
||||
} else {
|
||||
throw new \Exception("No matrix to convert", Matrix::E_NO_MATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload PHP's class __toString() method
|
||||
*
|
||||
* PHP magic method for "echoing" this object without a specific method called
|
||||
* Will use {@link Matrix::toString()} with no parameters for it's return.
|
||||
*
|
||||
* @return string Returns the $matrix value in string format
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Matrix Array
|
||||
*
|
||||
* Will return the matrix array of the current instance.
|
||||
*
|
||||
* @return array The matrix array of the current instance
|
||||
*/
|
||||
public function getArray()
|
||||
{
|
||||
return $this->matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formatted Matrix output for use in console
|
||||
*
|
||||
* Will output the matrix in 'pretty' format, if used with 'echo' and
|
||||
* HTML, surround it by the '<<pre>>' and '<</pre>>' tags to display properly
|
||||
*
|
||||
* @param int $width The width of printing space to use
|
||||
* @param array|bool $mArray Matrix array, defaults to $this->matrix
|
||||
* @return string "Pretty-Printed" matrix in ASCII format
|
||||
*/
|
||||
public function prettyPrint($width=80, $mArray=false)
|
||||
{
|
||||
if(!$mArray) $mArray = $this->matrix;
|
||||
if(!$this->_verify($mArray)) return false;
|
||||
|
||||
$out = "";
|
||||
$aCount = count($mArray[0]);
|
||||
$space = floor(($width-4)/$aCount);
|
||||
$space_2 = floor($space/2);
|
||||
|
||||
foreach($mArray as $row)
|
||||
{
|
||||
$out .= sprintf("| %{$space_2}.2f", $row[0]);
|
||||
for($i=1;$i<$aCount;$i++)
|
||||
{
|
||||
$out .= sprintf("%{$space}.2f", $row[$i]);
|
||||
}
|
||||
$out .= sprintf("%{$space_2}s |\n", " ");
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two matrices together
|
||||
*
|
||||
* Will add the inputted Matrix to the current instance, and return
|
||||
* the result as Matrix class.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Matrix_addition
|
||||
* @param Matrix $nMatrix Matrix class to be added to current instance
|
||||
* @return Matrix The result of the addition
|
||||
* @throws \Exception $msg of exception explains problem
|
||||
*/
|
||||
public function addMatrix(Matrix $nMatrix)
|
||||
{
|
||||
if(!$this->_verify() || !$nMatrix->_verify())
|
||||
throw new \Exception("Matrices have varying column sizes", Matrix::E_INVALID_MATRIX);
|
||||
|
||||
$matrix1 = $this->getArray();
|
||||
$matrix2 = $nMatrix->getArray();
|
||||
if((count($matrix1)!=count($matrix2)) || (count($matrix1[0])!=count($matrix2[0])))
|
||||
{
|
||||
$m1 = $this->toString($matrix1);
|
||||
$m2 = $this->toString($matrix2);
|
||||
throw new \Exception("The rows and/or columns '{$m1}' and '{$m2}' are not the same", Matrix::E_NOT_EQUAL);
|
||||
}
|
||||
|
||||
$rArray = array();
|
||||
for($row=0;$row<count($matrix1);$row++) {
|
||||
for($col=0;$col<count($matrix1[0]);$col++) {
|
||||
$rArray[$row][$col] = $matrix1[$row][$col] + $matrix2[$row][$col];
|
||||
}
|
||||
}
|
||||
$rMatrix = new Matrix($this->toString($rArray));
|
||||
return $rMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract Matrices
|
||||
*
|
||||
* Will subtract the inputted Matrix from the current instance, and return
|
||||
* the result as Matrix class.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Matrix_subtraction
|
||||
* @param Matrix $nMatrix Matrix class to be subtracted from current instance
|
||||
* @return Matrix The result of the subtraction
|
||||
* @throws \Exception $msg of exception explains problem
|
||||
*/
|
||||
public function subMatrix(Matrix $nMatrix)
|
||||
{
|
||||
if(!$this->_verify() || !$nMatrix->_verify())
|
||||
throw new \Exception("Matrices have varying column sizes", Matrix::E_INVALID_MATRIX);
|
||||
|
||||
$matrix1 = $this->getArray();
|
||||
$matrix2 = $nMatrix->getArray();
|
||||
if((count($matrix1)!=count($matrix2)) || (count($matrix1[0])!=count($matrix2[0])))
|
||||
{
|
||||
$m1 = $this->toString($matrix1);
|
||||
$m2 = $this->toString($matrix2);
|
||||
throw new \Exception("The rows and/or columns '{$m1}' and '{$m2}' are not the same", Matrix::E_NOT_EQUAL);
|
||||
}
|
||||
|
||||
$rArray = array();
|
||||
for($row=0;$row<count($matrix1);$row++) {
|
||||
for($col=0;$col<count($matrix1[0]);$col++) {
|
||||
$rArray[$row][$col] = $matrix1[$row][$col] - $matrix2[$row][$col];
|
||||
}
|
||||
}
|
||||
$rMatrix = new Matrix($this->toString($rArray));
|
||||
return $rMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply current matrix by a scalar value
|
||||
*
|
||||
* Multiplies a matrix by a scalar value (int/float/etc) (constant, ie '2')
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Scalar_multiplication
|
||||
* @param float $k The value to multiply the matrix by
|
||||
* @return Matrix Returns a new Matrix instance with the result
|
||||
* @throws \Exception if the instance matrix is not valid
|
||||
*/
|
||||
public function mpScalar($k)
|
||||
{
|
||||
//we'll verify a true matrix to ... help the user
|
||||
if(!$this->_verify())
|
||||
throw new \Exception("Matrix '{$this}' has varying column sizes", Matrix::E_INVALID_MATRIX);
|
||||
|
||||
$cArray = $this->getArray();
|
||||
$rArray = array();
|
||||
$rows = count($cArray);
|
||||
$cols = count($cArray[0]);
|
||||
for($i=0;$i<$rows;$i++) {
|
||||
for($j=0;$j<$cols;$j++) {
|
||||
$rArray[$i][$j] = $cArray[$i][$j] * $k;
|
||||
}
|
||||
}
|
||||
$rMatrix = new Matrix($this->toString($rArray));
|
||||
return $rMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Matrix Determinant
|
||||
*
|
||||
* Finds the determinant of the square matrix, user should not use
|
||||
* the parameter, as that is meant to allow recursive calling
|
||||
* of this function from within itself.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Matrix_determinant
|
||||
* @param array|bool $mArray The array to find a determinate of
|
||||
* @return float The Determinate of the square matrix
|
||||
* @throws \Exception If matrix is 1,1 or is not square
|
||||
*/
|
||||
public function getDeterminant($mArray = false)
|
||||
{
|
||||
if(!$mArray) $mArray = $this->matrix;
|
||||
//print_r($mArray);
|
||||
if(!$this->isSquare($mArray))
|
||||
throw new \Exception("'{$this}' is not a square matrix", Matrix::E_NOT_SQUARE);
|
||||
|
||||
$n = $this->_getN($mArray);
|
||||
if($n < 1){
|
||||
// @codeCoverageIgnoreStart
|
||||
// Should never get this far
|
||||
throw new \Exception("No Matrix", Matrix::E_NO_MATRIX);
|
||||
// @codeCoverageIgnoreEnd
|
||||
} elseif ($n == 1) {
|
||||
$det = $mArray[0][0];
|
||||
} elseif ($n == 2) {
|
||||
$det = $mArray[0][0]*$mArray[1][1] - $mArray[1][0]*$mArray[0][1];
|
||||
} else {
|
||||
$det = 0;
|
||||
$nArray = array();
|
||||
for($j1=0;$j1<$n;$j1++) {
|
||||
for($i=1;$i<$n;$i++) {
|
||||
$j2 = 0;
|
||||
for($j=0;$j<$n;$j++) {
|
||||
if($j==$j1) {
|
||||
continue;
|
||||
}
|
||||
$nArray[$i-1][$j2] = $mArray[$i][$j];
|
||||
$j2++;
|
||||
}
|
||||
}
|
||||
$det += pow(-1,2+$j1)*$mArray[0][$j1]*$this->getDeterminant($nArray);
|
||||
}
|
||||
}
|
||||
return $det;
|
||||
}
|
||||
|
||||
/**
|
||||
* coFactor Matrix
|
||||
*
|
||||
* Will return a Matrix of coFactors for the matrix provided, or an array
|
||||
* of the matrix as is the default.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Matrix_cofactors
|
||||
* @param array|bool $cArray A matrix in array format (or $this->matrix by default)
|
||||
* @param bool $asArray When set to true, will return an array, when false a Matrix Object
|
||||
* @return Matrix|array A matrix of coFactors for the array provided (or current matrix)
|
||||
* @throws \Exception if the matrix is not square
|
||||
*/
|
||||
public function coFactor($cArray=false,$asArray=true)
|
||||
{
|
||||
if(!$cArray) $cArray = $this->matrix;
|
||||
if(!$this->isSquare($cArray))
|
||||
throw new \Exception("'{$this}' is not a square matrix", Matrix::E_NOT_SQUARE);
|
||||
|
||||
$n = $this->_getN($cArray);
|
||||
$minor = array();
|
||||
$rArray = array();
|
||||
|
||||
for($j=0;$j<$n;$j++){
|
||||
for($i=0;$i<$n;$i++) {
|
||||
//Form the adjugate
|
||||
$i1 = 0;
|
||||
for($ii=0;$ii<$n;$ii++) {
|
||||
if($ii==$i) {
|
||||
continue;
|
||||
}
|
||||
$j1=0;
|
||||
for($jj=0;$jj<$n;$jj++) {
|
||||
if($jj==$j) {
|
||||
continue;
|
||||
}
|
||||
$minor[$i1][$j1] = $cArray[$ii][$jj];
|
||||
$j1++;
|
||||
}
|
||||
$i1++;
|
||||
}
|
||||
$det = $this->getDeterminant($minor);
|
||||
$rArray[$i][$j] = pow(-1,$i+$j+2)*$det;
|
||||
}
|
||||
}
|
||||
if($asArray==false){
|
||||
$rMatrix = new Matrix($this->toString($rArray));
|
||||
return $rMatrix;
|
||||
} else {
|
||||
return $rArray;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Will transpose the current matrix or array provided
|
||||
*
|
||||
* Transposes the current matrix, or the array provided
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Matrix_transpose
|
||||
* @param array|bool $cArray the array to transpose (defaults to $this->matrix)
|
||||
* @param bool $asArray whether to return an array or Matrix object
|
||||
* @return array|Matrix Defaults to returning an array of the transposed matrix
|
||||
* @throws \Exception if the matrix is not square
|
||||
*/
|
||||
public function transpose($cArray=false,$asArray=true)
|
||||
{
|
||||
if(!$cArray) $cArray = $this->matrix;
|
||||
if(!$this->isSquare($cArray))
|
||||
throw new \Exception("'{$this}' is not a square matrix", Matrix::E_NOT_SQUARE);
|
||||
|
||||
$n = $this->_getN();
|
||||
$nArray = array();
|
||||
for($i=0;$i<$n;$i++) {
|
||||
for($j=0;$j<$n;$j++) {
|
||||
$nArray[$j][$i] = $cArray[$i][$j];
|
||||
}
|
||||
}
|
||||
if($asArray==true) {
|
||||
return $nArray;
|
||||
} else {
|
||||
$nMatrix = new Matrix($this->toString($nArray));
|
||||
return $nMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjugate Matrix
|
||||
*
|
||||
* Will return the Adjugate matrix of the array provided
|
||||
* or the current matrix instance if not provided.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Adjugate_matrix
|
||||
* @param array|bool $cArray Defaults to $this->matrix if not provided
|
||||
* @param bool $asArray Whether to return an array or Matrix object
|
||||
* @return array|Matrix Defaults to return the array of the Adjugate matrix
|
||||
*/
|
||||
public function adjugate($cArray=false,$asArray=true)
|
||||
{
|
||||
if(!$cArray) $cArray = $this->matrix;
|
||||
$rArray = $this->transpose($this->coFactor($cArray));
|
||||
if($asArray==true)
|
||||
return $rArray;
|
||||
|
||||
$rMatrix = new Matrix($this->toString($rArray));
|
||||
return $rMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of current matrix
|
||||
*
|
||||
* Will give the inverse of the array provided or the current matrix
|
||||
* Matrix returned denoted by A^-1
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Inverse_matrix
|
||||
* @param array|bool $cArray Array to invert (defaults to $this->matrix)
|
||||
* @return Matrix By default returns a new instance of Matrix
|
||||
* @throws \Exception for any number of reasons that would make the inverse not available
|
||||
*/
|
||||
public function inverse($cArray = false)
|
||||
{
|
||||
if(!$cArray) $cArray = $this->matrix;
|
||||
|
||||
$det = $this->getDeterminant($cArray);
|
||||
if($det == 0)
|
||||
throw new \Exception("Determinant of {$this} is 0, No Inverse found", Matrix::E_NO_INVERSE);
|
||||
|
||||
|
||||
$scalar = 1/$det;
|
||||
$adj = $this->adjugate($cArray, false);
|
||||
$iMatrix = $adj->mpScalar($scalar);
|
||||
return $iMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply Matrices
|
||||
*
|
||||
* This function will multiply the current matrix with the matrix provided.
|
||||
* If current Matrix is denoted by 'A' and the inputted is denoted by 'B',
|
||||
* When written, this will return AB.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Matrix_multiplication
|
||||
* @param Matrix $bMatrix The matrix to multiply with the current
|
||||
* @return Matrix The result of multiplication.
|
||||
* @throws \Exception $msg explains why operation failed
|
||||
*/
|
||||
public function mpMatrix(Matrix $bMatrix)
|
||||
{
|
||||
if(!$this->_verify() || !$bMatrix->_verify()) {
|
||||
// @codeCoverageIgnoreStart
|
||||
// Should never get this far
|
||||
$eM1 = $this->toString();
|
||||
$eM2 = $bMatrix->toString();
|
||||
throw new \Exception("Either '{$eM1}' and/or '{$eM2}' is not a valid Matrix", Matrix::E_INVALID_MATRIX);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$aArray = $this->matrix;
|
||||
$bArray = $bMatrix->getArray();
|
||||
|
||||
//The number of columns in A must match the number of rows in B
|
||||
if(count($aArray[0]) != count($bArray)) {
|
||||
$mA = $this->toString();
|
||||
$mB = $bMatrix->toString();
|
||||
throw new \Exception("Columns in '{$mA}' don't match Rows of '{$mB}'", Matrix::E_NOT_EQUAL);
|
||||
}
|
||||
|
||||
$rArray = array();
|
||||
|
||||
//Loop through rows of Matrix A
|
||||
for($i=0;$i<count($aArray);$i++) {
|
||||
//Loop through the columns of Matrix B
|
||||
for($j=0;$j<count($bArray[0]);$j++) {
|
||||
$value = 0;
|
||||
//loop through the rows of Matrix B
|
||||
for($k=0;$k<count($bArray);$k++) {
|
||||
$value += $aArray[$i][$k] * $bArray[$k][$j];
|
||||
}
|
||||
$rArray[$i][$j] = $value;
|
||||
}
|
||||
}
|
||||
$rMatrix = new Matrix($this->toString($rArray));
|
||||
return $rMatrix;
|
||||
}
|
||||
}
|
||||
?>
|
593
Laravel/vendor/jlawrence/eos/src/Parser.php
vendored
Normal file
593
Laravel/vendor/jlawrence/eos/src/Parser.php
vendored
Normal file
@@ -0,0 +1,593 @@
|
||||
<?php
|
||||
/**
|
||||
* Equation Operating System Classes.
|
||||
*
|
||||
* This class was created for the safe parsing of mathematical equations
|
||||
* in PHP. There is a need for a way to successfully parse equations
|
||||
* in PHP that do NOT require the use of `eval`. `eval` at its core
|
||||
* opens the system using it to so many security vulnerabilities it is oft
|
||||
* suggested /never/ to use it, and for good reason. This class set will
|
||||
* successfully take an equation, parse it, and provide solutions to the
|
||||
* developer. It is a safe way to evaluate expressions without putting
|
||||
* the system at risk.
|
||||
*
|
||||
*
|
||||
* @author Jon Lawrence <jlawrence11@gmail.com>
|
||||
* @copyright Copyright ©2005-2015, Jon Lawrence
|
||||
* @license http://opensource.org/licenses/LGPL-2.1 LGPL 2.1 License
|
||||
* @version 3.0.0
|
||||
*/
|
||||
|
||||
namespace jlawrence\eos;
|
||||
|
||||
|
||||
/**
|
||||
* Equation Operating System (EOS) Parser
|
||||
*
|
||||
* A class that can safely parse mathematical equations. Re-written portions
|
||||
* from version 2.x to be extend-able with custom functions.
|
||||
*
|
||||
* @author Jon Lawrence <jlawrence11@gmail.com>
|
||||
* @copyright Copyright ©2005-2015, Jon Lawrence
|
||||
* @license http://opensource.org/licenses/LGPL-2.1 LGPL 2.1 License
|
||||
* @version 3.0.0
|
||||
*/
|
||||
class Parser {
|
||||
|
||||
/**
|
||||
* @var string Infix equation
|
||||
* Public so advanced/user-defined/etc can access it when throwing exceptions.
|
||||
*/
|
||||
public static $inFix;
|
||||
|
||||
/**
|
||||
* @var array Opening and closing selectors
|
||||
*/
|
||||
protected static $SEP = array(
|
||||
'open' => array('(', '['),
|
||||
'close' => array(')', ']')
|
||||
);
|
||||
|
||||
// Top precedence following operator - not in use
|
||||
protected static $SGL = array('!');
|
||||
|
||||
// Order of operations arrays follow
|
||||
protected static $ST = array('^', '!');
|
||||
protected static $ST1 = array('/', '*', '%');
|
||||
protected static $ST2 = array('+', '-');
|
||||
|
||||
/**
|
||||
* @var array Allowed functions
|
||||
*/
|
||||
protected static $FNC = array(
|
||||
'sin', 'cos', 'tan',
|
||||
'csc', 'sec', 'cot',
|
||||
'abs', 'ln', 'sqrt'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array Advanced functions container
|
||||
*/
|
||||
protected static $AFNC = array();
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
public static function init() {
|
||||
if (empty(self::$AFNC)) {
|
||||
//No advanced functions yet, so this function has not run, do so now.
|
||||
self::$AFNC = AdvancedFunctions::map();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Advanced Function Class
|
||||
*
|
||||
* Adds a function class to the parser for user/programmer defined
|
||||
* functions that can be parsed with the parser. For example
|
||||
* class structure see jlawrence\eos\AdvancedFunctions.
|
||||
* Class must be static, and must have a function named 'map'
|
||||
*
|
||||
* @param string $class Fully Qualified String to class (must include namespace)
|
||||
* @return bool True on success
|
||||
* @throws \Exception When the added class doesn't have the 'map' function or doesn't exist.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public static function addFunctionClass($class)
|
||||
{
|
||||
self::init();
|
||||
if(is_callable("{$class}::map")) {
|
||||
$a = call_user_func($class.'::map');
|
||||
self::$AFNC = array_merge($a, self::$AFNC);
|
||||
} else {
|
||||
throw new \Exception("{$class}::map() is not callable");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Infix for opening closing pair matches.
|
||||
*
|
||||
* This function is meant to solely check to make sure every opening
|
||||
* statement has a matching closing one, and throws an exception if
|
||||
* it doesn't.
|
||||
*
|
||||
* @param string $infix Equation to check
|
||||
* @throws \Exception if malformed.
|
||||
* @return Bool true if passes - throws an exception if not.
|
||||
*/
|
||||
private static function checkInfix($infix) {
|
||||
self::init();
|
||||
if(trim($infix) == "") {
|
||||
throw new \Exception("No Equation given", Math::E_NO_EQ);
|
||||
}
|
||||
//Make sure we have the same number of '(' as we do ')'
|
||||
// and the same # of '[' as we do ']'
|
||||
if(substr_count($infix, '(') != substr_count($infix, ')')) {
|
||||
throw new \Exception("Mismatched parenthesis in ". self::$inFix, Math::E_NO_SET);
|
||||
} elseif(substr_count($infix, '[') != substr_count($infix, ']')) {
|
||||
throw new \Exception("Mismatched brackets in '". self::$inFix, Math::E_NO_SET);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Infix to Postfix
|
||||
*
|
||||
* Converts an infix (standard) equation to postfix (RPN) notation.
|
||||
* Sets the internal variable $this->postFix for the Parser::solvePF()
|
||||
* function to use.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Infix_notation Infix Notation
|
||||
* @link http://en.wikipedia.org/wiki/Reverse_Polish_notation Reverse Polish Notation
|
||||
* @param string $infix A standard notation equation
|
||||
* @throws \Exception When parenthesis are mismatched
|
||||
* @return array Fully formed RPN Stack
|
||||
*/
|
||||
public static function in2post($infix) {
|
||||
// if an equation was not passed, use the one that was passed in the constructor
|
||||
//$infix = (isset($infix)) ? $infix : $this->inFix;
|
||||
|
||||
//check to make sure 'valid' equation
|
||||
self::checkInfix($infix);
|
||||
$pf = array();
|
||||
$ops = new Stack();
|
||||
//$vars = new Stack();
|
||||
|
||||
// remove all white-space
|
||||
$infix = preg_replace("/\s/", "", $infix);
|
||||
|
||||
// Create postfix array index
|
||||
$pfIndex = 0;
|
||||
|
||||
//what was the last character? (useful for discerning between a sign for negation and subtraction)
|
||||
$lChar = '';
|
||||
|
||||
//loop through all the characters and start doing stuff ^^
|
||||
for($i=0;$i<strlen($infix);$i++) {
|
||||
// pull out 1 character from the string
|
||||
$chr = substr($infix, $i, 1);
|
||||
|
||||
// if the character is numerical
|
||||
if(preg_match('/[0-9.]/i', $chr)) {
|
||||
// if the previous character was not a '-' or a number
|
||||
if((!preg_match('/[0-9.]/i', $lChar) && ($lChar != "")) && (isset($pf[$pfIndex]) && ($pf[$pfIndex]!="-")))
|
||||
$pfIndex++; // increase the index so as not to overlap anything
|
||||
// Add the number character to the array
|
||||
if(isset($pf[$pfIndex])) {
|
||||
$pf[$pfIndex] .= $chr;
|
||||
} else {
|
||||
$pf[$pfIndex] = $chr;
|
||||
}
|
||||
|
||||
}
|
||||
// If the character opens a set e.g. '(' or '['
|
||||
elseif(in_array($chr, self::$SEP['open'])) {
|
||||
// if the last character was a number, place an assumed '*' on the stack
|
||||
if(preg_match('/[0-9.]/i', $lChar))
|
||||
$ops->push('*');
|
||||
|
||||
$ops->push($chr);
|
||||
}
|
||||
// if the character closes a set e.g. ')' or ']'
|
||||
elseif(in_array($chr, self::$SEP['close'])) {
|
||||
// find what set it was i.e. matches ')' with '(' or ']' with '['
|
||||
$key = array_search($chr, self::$SEP['close']);
|
||||
// while the operator on the stack isn't the matching pair...pop it off
|
||||
while($ops->peek() != self::$SEP['open'][$key]) {
|
||||
$nchr = $ops->pop();
|
||||
if($nchr)
|
||||
$pf[++$pfIndex] = $nchr;
|
||||
else {
|
||||
//Should NEVER get here...
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \Exception("Error while searching for '". self::$SEP['open'][$key] ."' in ". self::$inFix, Math::E_NO_SET);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
$ops->pop();
|
||||
}
|
||||
// If a special operator that has precedence over everything else
|
||||
elseif(in_array($chr, self::$ST)) {
|
||||
while(in_array($ops->peek(), self::$ST))
|
||||
$pf[++$pfIndex] = $ops->pop();
|
||||
$ops->push($chr);
|
||||
$pfIndex++;
|
||||
}
|
||||
// Any other operator other than '+' and '-'
|
||||
elseif(in_array($chr, self::$ST1)) {
|
||||
while(in_array($ops->peek(), self::$ST1) || in_array($ops->peek(), self::$ST))
|
||||
$pf[++$pfIndex] = $ops->pop();
|
||||
|
||||
$ops->push($chr);
|
||||
$pfIndex++;
|
||||
}
|
||||
// if a '+' or '-'
|
||||
elseif(in_array($chr, self::$ST2)) {
|
||||
// if it is a '-' and the character before it was an operator or nothingness (e.g. it negates a number)
|
||||
if((in_array($lChar, array_merge(self::$ST1, self::$ST2, self::$ST, self::$SEP['open'])) || $lChar=="") && $chr=="-") {
|
||||
// increase the index because there is no reason that it shouldn't..
|
||||
$pfIndex++;
|
||||
$pf[$pfIndex] = $chr;
|
||||
}
|
||||
// Otherwise it will function like a normal operator
|
||||
else {
|
||||
while(in_array($ops->peek(), array_merge(self::$ST1, self::$ST2, self::$ST)))
|
||||
$pf[++$pfIndex] = $ops->pop();
|
||||
$ops->push($chr);
|
||||
$pfIndex++;
|
||||
}
|
||||
}
|
||||
// make sure we record this character to be referred to by the next one
|
||||
$lChar = $chr;
|
||||
}
|
||||
// if there is anything on the stack after we are done...add it to the back of the RPN array
|
||||
while(($tmp = $ops->pop()) !== false)
|
||||
$pf[++$pfIndex] = $tmp;
|
||||
|
||||
// re-index the array at 0
|
||||
$pf = array_values($pf);
|
||||
|
||||
// set the private variable for later use if needed
|
||||
//self::$postFix = $pf;
|
||||
|
||||
// return the RPN array in case developer wants to use it for some insane reason (bug testing ;] )
|
||||
// Also... because we pass it right in to the RPN solver. So I guess there's that too.
|
||||
return $pf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Solve Postfix (RPN)
|
||||
*
|
||||
* This function will solve a RPN array. Default action is to solve
|
||||
* the RPN array stored in the class from Parser::in2post(), can take
|
||||
* an array input to solve as well, though default action is preferred.
|
||||
*
|
||||
* @link http://en.wikipedia.org/wiki/Reverse_Polish_notation Postix Notation
|
||||
* @param array $pfArray RPN formatted array. Optional.
|
||||
* @throws \Exception on division by 0
|
||||
* @return float Result of the operation.
|
||||
*/
|
||||
public static function solvePF($pfArray) {
|
||||
$pf = $pfArray;
|
||||
|
||||
// create our temporary function variables
|
||||
$temp = array();
|
||||
//$tot = 0;
|
||||
$hold = 0;
|
||||
|
||||
// Loop through each number/operator
|
||||
for($i=0;$i<count($pf); $i++) {
|
||||
// If the string isn't an operator, add it to the temp var as a holding place
|
||||
if(!in_array($pf[$i], array_merge(self::$ST, self::$ST1, self::$ST2))) {
|
||||
$temp[$hold++] = $pf[$i];
|
||||
}
|
||||
// ...Otherwise perform the operator on the last two numbers
|
||||
else {
|
||||
switch ($pf[$i]) {
|
||||
case '+':
|
||||
$temp[$hold-2] = $temp[$hold-2] + $temp[$hold-1];
|
||||
break;
|
||||
case '-':
|
||||
$temp[$hold-2] = $temp[$hold-2] - $temp[$hold-1];
|
||||
break;
|
||||
case '*':
|
||||
$temp[$hold-2] = $temp[$hold-2] * $temp[$hold-1];
|
||||
break;
|
||||
case '/':
|
||||
if($temp[$hold-1] == 0) {
|
||||
throw new \Exception("Division by 0 on: '{$temp[$hold-2]} / {$temp[$hold-1]}' in ". self::$inFix, Math::E_DIV_ZERO);
|
||||
}
|
||||
$temp[$hold-2] = $temp[$hold-2] / $temp[$hold-1];
|
||||
break;
|
||||
case '^':
|
||||
$temp[$hold-2] = pow($temp[$hold-2], $temp[$hold-1]);
|
||||
break;
|
||||
case '!':
|
||||
$temp[$hold-1] = self::factorial($temp[$hold-1]);
|
||||
$hold++;
|
||||
break;
|
||||
case '%':
|
||||
if($temp[$hold-1] == 0) {
|
||||
throw new \Exception("Division by 0 on: '{$temp[$hold-2]} % {$temp[$hold-1]}' in ". self::$inFix, Math::E_DIV_ZERO);
|
||||
}
|
||||
$temp[$hold-2] = bcmod($temp[$hold-2], $temp[$hold-1]);
|
||||
break;
|
||||
}
|
||||
// Decrease the hold var to one above where the last number is
|
||||
$hold = $hold-1;
|
||||
}
|
||||
}
|
||||
|
||||
// return the last number in the array
|
||||
return $temp[$hold-1];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Solve
|
||||
*
|
||||
* This function is called by the user to solve an equation within the parser system
|
||||
* No internal functions or added advanced functions should ever call this. Sets
|
||||
* the internal $infix variable for use in thrown exceptions. The variable array must
|
||||
* be in the format of 'variable' => value. If variable array is scalar (ie 5), all
|
||||
* variables will be replaced with it.
|
||||
*
|
||||
* @param string $equation Equation to Solve
|
||||
* @param array|double $values variable values
|
||||
* @return float Answer to the equation
|
||||
*/
|
||||
public static function solve($equation, $values = null) {
|
||||
if(is_array($equation)) {
|
||||
return self::solvePF($equation);
|
||||
} else {
|
||||
self::$inFix = $equation;
|
||||
return self::solveIF($equation, $values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Solve Infix (Standard) Notation Equation
|
||||
*
|
||||
* Will take a standard equation with optional variables and solve it.
|
||||
* This function is the one for programmers making modules for this
|
||||
* package should call as it does not set the internal variable for
|
||||
* the equation. This should not be used by the programmer/user that
|
||||
* is using this package to solve equations.
|
||||
*
|
||||
* @param string $infix Standard Equation to solve
|
||||
* @param string|array $vArray Variable replacement
|
||||
* @throws \Exception On division by zero or NaN
|
||||
* @return float Solved equation
|
||||
*/
|
||||
public static function solveIF($infix, $vArray = null) {
|
||||
//Check to make sure a 'valid' expression
|
||||
self::checkInfix($infix);
|
||||
|
||||
//$ops = new Stack();
|
||||
//$vars = new Stack();
|
||||
$hand = null;
|
||||
|
||||
//remove all white-space
|
||||
$infix = preg_replace("/\s/", "", $infix);
|
||||
|
||||
$infix = self::checkAdvancedInput($infix,$vArray);
|
||||
|
||||
// Finds all the 'functions' within the equation and calculates them
|
||||
//Nested parenthesis are now a go!
|
||||
while((preg_match("/(". implode("|", self::$FNC) . ")\(((?:[^()]|\((?2)\))*+)\)/", $infix, $match)) != 0) {
|
||||
$func = self::solveIF($match[2], $vArray);
|
||||
switch($match[1]) {
|
||||
case "cos":
|
||||
$ans = Trig::cos($func);
|
||||
break;
|
||||
case "sin":
|
||||
$ans = Trig::sin($func);
|
||||
break;
|
||||
case "tan":
|
||||
$ans = Trig::tan($func);
|
||||
break;
|
||||
case "sec":
|
||||
$ans = Trig::sec($func);
|
||||
break;
|
||||
case "csc":
|
||||
$ans = Trig::csc($func);
|
||||
break;
|
||||
case "cot":
|
||||
$ans = Trig::cot($func);
|
||||
break;
|
||||
case "abs":
|
||||
$ans = abs($func);
|
||||
break;
|
||||
case "ln":
|
||||
$ans = log($func);
|
||||
if(is_nan($ans) || is_infinite($ans)) {
|
||||
throw new \Exception("Result of 'ln({$func}) = {$ans}' is either infinite or a non-number in ". self::$inFix, Math::E_NAN);
|
||||
}
|
||||
break;
|
||||
case "sqrt":
|
||||
if($func < 0) {
|
||||
throw new \Exception("Result of 'sqrt({$func}) = i' in ". self::$inFix .". We can't handle imaginary numbers", Math::E_NAN);
|
||||
}
|
||||
$ans = sqrt($func);
|
||||
break;
|
||||
// @codeCoverageIgnoreStart
|
||||
default:
|
||||
$ans = 0;
|
||||
break;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$infix = str_replace($match[0], "({$ans})", $infix);
|
||||
}
|
||||
|
||||
//replace scientific notation with normal notation (2e-9 to 2*10^-9)
|
||||
$infix = preg_replace('/([\d])([eE])(-?\d)/', '$1*10^$3', $infix);
|
||||
|
||||
$infix = self::replaceVars($infix, $vArray);
|
||||
|
||||
return self::solvePF(self::in2post($infix));
|
||||
}
|
||||
|
||||
/**
|
||||
* checkAdvancedInput
|
||||
*
|
||||
* Will take the input from `Parser::solveIF()` and solve all the advanced functions
|
||||
* that exist within it, returning it to the function when done for further
|
||||
* processing.
|
||||
*
|
||||
* @param string $input Check for advanced functions, recursively go through them.
|
||||
* @param array|int|null $vArray Variables from user-input
|
||||
* @return string The input with all advanced functions solved for.
|
||||
*/
|
||||
protected static function checkAdvancedInput($input, $vArray)
|
||||
{
|
||||
$infix = $input;
|
||||
//Advanced/User-defined functions
|
||||
while((preg_match("/(". implode("|", array_keys(self::$AFNC)) . ")\(((?:[^()]|\((?2)\))*+)\)/", $infix, $match)) != 0) {
|
||||
$method = self::$AFNC[$match[1]];
|
||||
if(stripos($match[2], '(') !== false) {
|
||||
$match[2] = self::checkAdvancedInput($match[2], $vArray);
|
||||
}
|
||||
$ans = call_user_func($method, $match[2], $vArray);
|
||||
$infix = str_replace($match[0], "({$ans})", $infix);
|
||||
}
|
||||
return $infix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $infix
|
||||
* @param array $vArray
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected static function replaceVars($infix, $vArray)
|
||||
{
|
||||
//Remove old '$' and '&' signis so the regex works properly.
|
||||
$infix = preg_replace('/[$&]/', "", $infix);
|
||||
//Find all the variables that were passed and replaces them
|
||||
while((preg_match('/([^a-zA-Z]){0,1}([a-zA-Z]+)([^a-zA-Z]){0,1}/', $infix, $match)) != 0) {
|
||||
|
||||
//remove notices by defining if undefined.
|
||||
if(!isset($match[3])) {
|
||||
$match[3] = "";
|
||||
}
|
||||
|
||||
// Ensure that the variable has an operator or something of that sort in front and back - if it doesn't, add an implied '*'
|
||||
if((!in_array($match[1], array_merge(self::$ST, self::$ST1, self::$ST2, self::$SEP['open'])) && $match[1] != "") || is_numeric($match[1])) //$this->SEP['close'] removed
|
||||
$front = "*";
|
||||
else
|
||||
$front = "";
|
||||
|
||||
if((!in_array($match[3], array_merge(self::$ST, self::$ST1, self::$ST2, self::$SEP['close'])) && $match[3] != "") || is_numeric($match[3])) //$this->SEP['open'] removed
|
||||
$back = "*";
|
||||
else
|
||||
$back = "";
|
||||
|
||||
//Make sure that the variable does have a replacement
|
||||
//First check for pi and e variables that wll automatically be replaced
|
||||
if(in_array(strtolower($match[2]), array('pi', 'e'))) {
|
||||
$t = (strtolower($match[2])=='pi') ? pi() : exp(1);
|
||||
$infix = str_replace($match[0], $match[1] . $front. $t. $back . $match[3], $infix);
|
||||
} elseif(!isset($vArray[$match[2]]) && (!is_array($vArray != "") && !is_numeric($vArray) && 0 !== $vArray)) {
|
||||
throw new \Exception("Variable replacement does not exist for '". $match[2] ."' in ". self::$inFix .".", Math::E_NO_VAR);
|
||||
} elseif(!isset($vArray[$match[2]]) && (!is_array($vArray != "") && is_numeric($vArray))) {
|
||||
$infix = str_replace($match[0], $match[1] . $front. $vArray. $back . $match[3], $infix);
|
||||
} elseif(isset($vArray[$match[2]])) {
|
||||
$infix = str_replace($match[0], $match[1] . $front. $vArray[$match[2]]. $back . $match[3], $infix);
|
||||
}
|
||||
}
|
||||
|
||||
return $infix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Solve factorial (!)
|
||||
*
|
||||
* Will take an integer and solve for it's factorial. Eg.
|
||||
* `5!` will become `1*2*3*4*5` = `120`
|
||||
* DONE:
|
||||
* Solve for non-integer factorials 2015/07/02
|
||||
*
|
||||
* @param float $num Non-negative real number to get factorial of
|
||||
* @throws \Exception if number is at or less than 0
|
||||
* @return float Solved factorial
|
||||
*/
|
||||
protected static function factorial($num) {
|
||||
if($num < 0) {
|
||||
throw new \Exception("Factorial Error: Factorials don't exist for numbers < 0 in ". self::$inFix, Math::E_NAN);
|
||||
}
|
||||
//A non-integer! Gamma that sucker up!
|
||||
if(intval($num) != $num) {
|
||||
return self::gamma($num + 1);
|
||||
}
|
||||
|
||||
$tot = 1;
|
||||
for($i=1;$i<=$num;$i++) {
|
||||
$tot *= $i;
|
||||
}
|
||||
|
||||
return $tot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gamma Function
|
||||
*
|
||||
* Because we can. This function exists as a catch-all for different
|
||||
* numerical approx. of gamma if I decide to add any past Lanczos'.
|
||||
*
|
||||
* @param $z Number to compute gamma from
|
||||
* @return float The gamma (hopefully, I'll test it after writing the code)
|
||||
*/
|
||||
public static function gamma($z)
|
||||
{
|
||||
return self::laGamma($z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lanczos Approximation
|
||||
*
|
||||
* The Lanczos Approximation method of finding gamma values
|
||||
*
|
||||
* @link http://www.rskey.org/CMS/index.php/the-library/11
|
||||
* @link http://algolist.manual.ru/maths/count_fast/gamma_function.php
|
||||
* @link https://en.wikipedia.org/wiki/Lanczos_approximation
|
||||
* @param $z Number to obtain the gamma of
|
||||
* @return float Answer
|
||||
*/
|
||||
protected static function laGamma($z)
|
||||
{
|
||||
// Set up coefficients
|
||||
$p = array(
|
||||
0 => 1.000000000190015,
|
||||
1 => 76.18009172947146,
|
||||
2 => -86.50532032941677,
|
||||
3 => 24.01409824083091,
|
||||
4 => -1.231739572450155,
|
||||
5 => 1.208650973866179E-3,
|
||||
6 => -5.395239384953E-6
|
||||
);
|
||||
|
||||
// Formula:
|
||||
// ((sqrt(2pi)/z)(p[0]+sum(p[n]/(z+n), 1, 6)))(z+5.5)^(z+0.5)*e^(-(z+5.5))
|
||||
|
||||
// Break it down now...
|
||||
$g1 = sqrt(2*pi())/$z;
|
||||
|
||||
// Next comes our summation
|
||||
$g2 =0;
|
||||
for($n=1;$n<=6;$n++) {
|
||||
$g2 += $p[$n]/($z+$n);
|
||||
}
|
||||
|
||||
// Don't forget to add p[0] to it...
|
||||
$g2 += $p[0];
|
||||
$g3 = pow($z+5.5, $z + .5);
|
||||
$g4 = exp(-($z+5.5));
|
||||
|
||||
//now just multiply them all together
|
||||
$gamma = $g1 * $g2 * $g3 * $g4;
|
||||
|
||||
return $gamma;
|
||||
}
|
||||
}
|
115
Laravel/vendor/jlawrence/eos/src/Stack.php
vendored
Normal file
115
Laravel/vendor/jlawrence/eos/src/Stack.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace jlawrence\eos;
|
||||
|
||||
/**
|
||||
* Basic Stack Class.
|
||||
*
|
||||
* Created for use with eqEOS. May eventually be replaced with native
|
||||
* PHP functions `array_pop()`, `array_push()`, and `end()`
|
||||
*
|
||||
* @author Jon Lawrence <jlawrence11@gmail.com>
|
||||
* @copyright Copyright ©2005-2015 Jon Lawrence
|
||||
* @license http://opensource.org/licenses/LGPL-2.1 LGPL 2.1 License
|
||||
* @package Math
|
||||
* @version 0.1
|
||||
*/
|
||||
class Stack {
|
||||
private $index;
|
||||
private $locArray;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Initializes the stack
|
||||
*/
|
||||
public function __construct() {
|
||||
//define the private vars
|
||||
$this->locArray = array();
|
||||
$this->index = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek
|
||||
*
|
||||
* Will view the last element of the stack without removing it
|
||||
*
|
||||
* @return mixed An element of the array or false if none exist
|
||||
*/
|
||||
public function peek() {
|
||||
if($this->index > -1)
|
||||
return $this->locArray[$this->index];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Poke
|
||||
*
|
||||
* Will add an element to the end of the stack
|
||||
*
|
||||
* @param mixed $data Element to add
|
||||
*/
|
||||
public function poke($data) {
|
||||
$this->locArray[++$this->index] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push
|
||||
*
|
||||
* Alias of {@see Stack::poke()}
|
||||
* Adds element to the stack
|
||||
*
|
||||
* @param mixed $data Element to add
|
||||
*/
|
||||
public function push($data) {
|
||||
//alias for 'poke'
|
||||
$this->poke($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop
|
||||
*
|
||||
* Retrieves an element from the end of the stack, and removes it from
|
||||
* the stack at the same time. If no elements, returns boolean false
|
||||
*
|
||||
* @return mixed Element at end of stack or false if none exist
|
||||
*/
|
||||
public function pop() {
|
||||
if($this->index > -1)
|
||||
{
|
||||
$this->index--;
|
||||
return $this->locArray[$this->index+1];
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear
|
||||
*
|
||||
* Clears the stack to be reused.
|
||||
*/
|
||||
public function clear() {
|
||||
$this->index = -1;
|
||||
$this->locArray = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Stack
|
||||
*
|
||||
* Returns the array of stack elements, keeping all, indexed at 0
|
||||
*
|
||||
* @return mixed Array of stack elements or false if none exist.
|
||||
*/
|
||||
public function getStack() {
|
||||
if($this->index > -1)
|
||||
{
|
||||
return array_values($this->locArray);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
75
Laravel/vendor/jlawrence/eos/src/Trig.php
vendored
Normal file
75
Laravel/vendor/jlawrence/eos/src/Trig.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by: Jon Lawrence on 2015-07-02 3:10 PM
|
||||
*/
|
||||
|
||||
namespace jlawrence\eos;
|
||||
|
||||
/**
|
||||
* Class Trig
|
||||
* @package jlawrence\Math
|
||||
*
|
||||
* Trig functions, primarily because there's a difference when dealing with
|
||||
* radians and degrees, and this class will help with that - defaulting
|
||||
* to radians, but allowing the default to be set to degrees for the
|
||||
* project. Thus simplifying the amount of calculations the user
|
||||
* of this project needs to do.
|
||||
*/
|
||||
class Trig
|
||||
{
|
||||
/**
|
||||
* @var bool Whether or not to convert to radians before calculation
|
||||
* (Meaning input is in degree form)
|
||||
*/
|
||||
public static $DEGREES = false;
|
||||
|
||||
protected static function getRadDeg($x)
|
||||
{
|
||||
if(self::$DEGREES == true) {
|
||||
return deg2rad($x);
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
|
||||
public static function cos($x)
|
||||
{
|
||||
return cos(self::getRadDeg($x));
|
||||
}
|
||||
|
||||
public static function sin($x)
|
||||
{
|
||||
return sin(self::getRadDeg($x));
|
||||
}
|
||||
|
||||
public static function tan($x)
|
||||
{
|
||||
return tan(self::getRadDeg($x));
|
||||
}
|
||||
|
||||
public static function sec($x)
|
||||
{
|
||||
$tmp = self::cos($x);
|
||||
if($tmp == 0)
|
||||
throw new \Exception("Division by 0 on: 'sec({$x}) = 1/cos({$x})' in ". Parser::$inFix, Math::E_DIV_ZERO);
|
||||
|
||||
return 1/$tmp;
|
||||
}
|
||||
|
||||
public static function csc($x)
|
||||
{
|
||||
$tmp = self::sin($x);
|
||||
if($tmp == 0)
|
||||
throw new \Exception("Division by 0 on: 'csc({$x})) = 1/sin({$x})' in ". Parser::$inFix, Math::E_DIV_ZERO);
|
||||
|
||||
return 1/$tmp;
|
||||
}
|
||||
|
||||
public static function cot($x)
|
||||
{
|
||||
$tmp = self::tan($x);
|
||||
if($tmp == 0)
|
||||
throw new \Exception("Division by 0 on: 'cot({$x})) = 1/tan({$x})' in ". Parser::$inFix, Math::E_DIV_ZERO);
|
||||
|
||||
return 1/$tmp;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user