|
Posted on January 23, 2012 @ 12:45:37 AM by Paul Meagher
Continuing on with my research into adding better matrix/vector capabilities to PHP, I decided to implement the basic arithmetic functions (addition, subtraction, division, multiplication) as vectorized functions. To make these functions concise and easy to remember, I used a system of function naming that involves prefixing the function call with a "v" (for "vector") and then using the first three letters of the arithmetic operation name (add, sub, div, mul) as the suffix:
- vadd($v, $addend): vector addition
- vsub($v, $subtrahend): vector subtaction
- vdiv($v, $divisor): vector division
- vmul($v, $factor): vector multiplication
In all cases, the first argument is a vector of numbers, followed by the value to apply to each element of the vector. The code below is proof-of-concept of how to vectorize these functions and is not meant as production-level code:
<?php /** * Set of functions that vectorize the basic arithmetic functions: * addition, subtraction, division, multiplication. No error * checking. */
// function for vectorized addition
function _add($addend1, $addend2) { return ($addend1 + $addend2); }
function vadd($v, $addend) { $size = count($v); $add_array = array_fill(0, $size, $addend); return array_map("_add", $v, $add_array); }
// function for vectorized subtraction
function _sub($minuend, $subtrahend) { return ($minuend - $subtrahend); }
function vsub($v, $subtrahend) { $size = count($v); $sub_array = array_fill(0, $size, $subtrahend); return array_map("_sub", $v, $sub_array); }
// function for vectorized multiplication
function _mul($factor1, $factor2) { return ($factor1 * $factor2); }
function vmul($v, $factor) { $size = count($v); $mul_array = array_fill(0, $size, $factor); return array_map("_mul", $v, $mul_array); }
// function for vectorized division
function _div($numerator, $divisor) { return ($numerator / $divisor); }
function vdiv($v, $divisor) { $size = count($v); $div_array = array_fill(0, $size, $divisor); return array_map("_div", $v, $div_array); }
$v = array(5, 10, 15); $arg = 5;
$b = vadd($v, $arg); print_r($b); echo "<br />";
$b = vsub($v, $arg); print_r($b); echo "<br />";
$b = vmul($v, $arg); print_r($b); echo "<br />";
$b = vdiv($v, $arg); print_r($b); echo "<br />";
// Output:
// Array ( [0] => 10 [1] => 15 [2] => 20 ) // Array ( [0] => 0 [1] => 5 [2] => 10 ) // Array ( [0] => 25 [1] => 50 [2] => 75 ) // Array ( [0] => 1 [1] => 2 [2] => 3 )
?>
The alternative to vectorized functions is the ad-hoc creation of loops to perform similar vectorized operations in your code. Think how much programming time and effort has been wasted coding loops to do vectorized arithmetic when there could be vectorized arithmetic functions available to do it all in one simple command.
This only touches the surface of the number of mathematical functions that should be vectorized in PHP (e.g., vsin, vcos, vexp, etc...) to make PHP a much more efficient language to program numeric-based algorithms. We could easily add a "v" suffix to all these function to indicate that they are all vector-based.
Another option to consider would be to go even further and have these functions handle matrix operations, with vectors being just the special case of a one-dimensional matrix. In that case, we might want to instead prefix all the functions with an "m" instead of a "v". I had considered this, but was too lazy to implement functions to handle the matrix case. This is a good exercise for the reader.
At the end of the day we should look at languages like Matlab/Octave to give us guidance on how to proceed with respect to the range of functions to vectorize and whether we should handle vector or matrix arguments to these functions. While we may not be able to use Matlab/Octave's concise syntax to code vectorized algorithms, we can develop slightly more verbose functions like vadd, vsub, vdiv, and vmul to efficiently code numeric algorithms.
|