blob: 9d796a55843337cc59d94d19566d2faefdc2745a [file] [log] [blame]
<?php
/**
* File containing the abstract ezcGraphPolynom class
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package Graph
* @version //autogentag//
* @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
*/
/**
* Provides a class for generic operations on polynoms
*
* This class is mainly used for internal representation of polynoms in the
* average dataset ezcGraphDataSetAveragePolynom.
*
* It provides only very basic mechanisms to work with polynoms, like adding of
* polynomes and evaluating the polynom with a given number, to calculate a
* point in the chart for a given value on the x axis.
*
* Beside this the __toString implementation may be used to echo the polynoms
* calculated by the least squares mechanism in the above mentioned average
* datasets. The class does not provide any options to customize the output.
*
* The class can be used like:
*
* <code>
* // Equivalent to: x^2 + .5
* $polynom = new ezcGraphPolynom( array( 2 => 1, 0 => .5 ) );
*
* // Calculate result for x = 1, echos: 1.5
* echo $polynom->evaluate( 1 ), PHP_EOL;
*
* // Build the sum with another polynom
* $polynom->add( new ezcGraphPolynom( array( 1 => 1 ) ) );
*
* // Print polynom, echos:
* // x^2 + x + 5.00e-1
* echo $polynom, PHP_EOL;
* </code>
*
* @version //autogentag//
* @package Graph
*/
class ezcGraphPolynom
{
/**
* Factors of the polynom
*
* An example:
* Polynom:
* 2 * x^3 + .5 * x - 3
* Array:
* array (
* (int) 3 => (float) 2,
* (int) 1 => (float) .5,
* (int) 0 => (float) -3,
* )
*
* @var array
*/
protected $values;
// @TODO: Introduce precision option for string output?
/**
* Constructor
*
* Constructs a polynom object from given array, where the key is the
* exponent and the value the factor.
* An example:
* Polynom:
* 2 * x^3 + .5 * x - 3
* Array:
* array (
* (int) 3 => (float) 2,
* (int) 1 => (float) .5,
* (int) 0 => (float) -3,
* )
*
* @param array $values Array with values
* @return ezcGraphPolynom
*/
public function __construct( array $values = array() )
{
foreach ( $values as $exponent => $factor )
{
$this->values[(int) $exponent] = (float) $factor;
}
}
/**
* Initialise a polygon
*
* Initialise a polygon of the given order. Sets all factors to 0.
*
* @param int $order Order of polygon
* @return ezcGraphPolynom Created polynom
*/
public function init( $order )
{
for ( $i = 0; $i <= $order; ++$i )
{
$this->values[$i] = 0;
}
return $this;
}
/**
* Return factor for one exponent
*
* @param int $exponent Exponent
* @return float Factor
*/
public function get( $exponent )
{
if ( !isset( $this->values[$exponent] ) )
{
return 0;
}
else
{
return $this->values[$exponent];
}
}
/**
* Set the factor for one exponent
*
* @param int $exponent Exponent
* @param float $factor Factor
* @return ezcGraphPolynom Modified polynom
*/
public function set( $exponent, $factor )
{
$this->values[(int) $exponent] = (float) $factor;
return $this;
}
/**
* Returns the order of the polynom
*
* @return int Polynom order
*/
public function getOrder()
{
return max( array_keys( $this->values ) );
}
/**
* Adds polynom to current polynom
*
* @param ezcGraphPolynom $polynom Polynom to add
* @return ezcGraphPolynom Modified polynom
*/
public function add( ezcGraphPolynom $polynom )
{
$order = max(
$this->getOrder(),
$polynom->getOrder()
);
for ( $i = 0; $i <= $order; ++$i )
{
$this->set( $i, $this->get( $i ) + $polynom->get( $i ) );
}
return $this;
}
/**
* Evaluate Polynom with a given value
*
* @param float $x Value
* @return float Result
*/
public function evaluate( $x )
{
$value = 0;
foreach ( $this->values as $exponent => $factor )
{
$value += $factor * pow( $x, $exponent );
}
return $value;
}
/**
* Returns a string represenation of the polynom
*
* @return string String representation of polynom
*/
public function __toString()
{
krsort( $this->values );
$string = '';
foreach ( $this->values as $exponent => $factor )
{
if ( $factor == 0 )
{
continue;
}
$string .= ( $factor < 0 ? ' - ' : ' + ' );
$factor = abs( $factor );
switch ( true )
{
case abs( 1 - $factor ) < .0001:
// No not append, if factor is ~1
break;
case $factor < 1:
case $factor >= 1000:
$string .= sprintf( '%.2e ', $factor );
break;
case $factor >= 100:
$string .= sprintf( '%.0f ', $factor );
break;
case $factor >= 10:
$string .= sprintf( '%.1f ', $factor );
break;
default:
$string .= sprintf( '%.2f ', $factor );
break;
}
switch ( true )
{
case $exponent > 1:
$string .= sprintf( 'x^%d', $exponent );
break;
case $exponent === 1:
$string .= 'x';
break;
case $exponent === 0:
if ( abs( 1 - $factor ) < .0001 )
{
$string .= '1';
}
break;
}
}
if ( substr( $string, 0, 3 ) === ' + ' )
{
$string = substr( $string, 3 );
}
else
{
$string = '-' . substr( $string, 3 );
}
return trim( $string );
}
}
?>