Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:7682 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 51191 invoked by uid 1010); 10 Feb 2004 00:53:18 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 51165 invoked from network); 10 Feb 2004 00:53:18 -0000 Received: from unknown (HELO mra03.ex.eclipse.net.uk) (212.104.129.88) by pb1.pair.com with SMTP; 10 Feb 2004 00:53:18 -0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by mra03.ex.eclipse.net.uk (Postfix) with ESMTP id 8CF242E3132 for ; Tue, 10 Feb 2004 00:52:42 +0000 (GMT) Received: from mra03.ex.eclipse.net.uk ([127.0.0.1]) by localhost (mra03.ex.eclipse.net.uk [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 12857-01-17 for ; Tue, 10 Feb 2004 00:52:42 +0000 (GMT) Received: from mooby (unknown [213.152.58.41]) by mra03.ex.eclipse.net.uk (Postfix) with ESMTP id A2CDB2E3116 for ; Tue, 10 Feb 2004 00:52:41 +0000 (GMT) To: Date: Tue, 10 Feb 2004 00:53:16 -0000 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0000_01C3EF70.4512EE30" X-Mailer: Microsoft Office Outlook, Build 11.0.5510 Thread-Index: AcPvbQXSKrirEUZHTXmUJmwM4FdlsQAAtQuQ X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 Message-ID: <20040210005241.A2CDB2E3116@mra03.ex.eclipse.net.uk> X-Virus-Scanned: by Eclipse VIRUSshield at eclipse.net.uk Subject: FW: [PATCH] Bug #24064: Standard deviation From: webjedi@hudzilla.eclipse.co.uk ("Paul Hudson") ------=_NextPart_000_0000_01C3EF70.4512EE30 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Er, either the php-internals MARC archive doesn't show all attachments, or my diff file got stripped en route for not having a .txt extension. I've attached it again, just to make sure. Paul -- -----Original Message----- From: Paul Hudson [mailto:webjedi@hudzilla.eclipse.co.uk] Sent: 10 February 2004 00:30 To: 'internals@lists.php.net' Subject: [PATCH] Bug #24064: Standard deviation Hi there, Bug #24064 (submitted by tularis@php.net) requests a standard deviation function for PHP. I realise that any of you could implement this in 10 minutes, but according to the bug database it is still Open so I figured I would give it a try myself! There are probably a dozen errors in the code and/or places where it could be better optimised, but I'm hoping one of you might be able to help with that. So, the attached diff file implements the function array_std_dev(), to calculate standard deviation using the deviation method. With the function in place, standard deviation is calculated like this: My first attempt at implementing this was using an extra array to buffer the deviations - this was more out of curiosity to see how the array stuff works. Sadly, it caused PHP to segfault and I couldn't figure out why - can any of you help me spot the brain fart? (I've attached the offending code in bad_stddev_code.txt) Yours, Paul PS: I'm not on the internals list, so I would appreciate it if you would CC me on your reply. ------=_NextPart_000_0000_01C3EF70.4512EE30 Content-Type: text/plain; name="array_std_dev_diff.txt" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="array_std_dev_diff.txt" diff -rubB php-snap/ext/standard/array.c php-new/ext/standard/array.c=0A= --- php-snap/ext/standard/array.c 2004-01-28 21:08:16.000000000 +0000=0A= +++ php-new/ext/standard/array.c 2004-02-09 23:57:14.590206400 +0000=0A= @@ -4229,6 +4229,77 @@=0A= }=0A= /* }}} */=0A= =0A= +=0A= +/* {{{ proto mixed array_std_dev(array input)=0A= + Returns the standard deviation of the array entries */=0A= +PHP_FUNCTION(array_std_dev)=0A= +{=0A= + zval **input,=0A= + **entry,=0A= + *entry_n;=0A= + int argc =3D ZEND_NUM_ARGS();=0A= + HashPosition pos;=0A= + double total =3D 0;=0A= + double mean;=0A= + int numelements =3D 0; // note this is calcuated by hand, not using = zend_hash_num_elements()=0A= + double deviation =3D 0;=0A= +=0A= + if (argc !=3D 1 || zend_get_parameters_ex(argc, &input) =3D=3D = FAILURE) {=0A= + WRONG_PARAM_COUNT;=0A= + }=0A= +=0A= + if (Z_TYPE_PP(input) !=3D IS_ARRAY) {=0A= + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be = an array");=0A= + return;=0A= + }=0A= +=0A= + ZVAL_LONG(return_value, 0);=0A= +=0A= + // step one: sum the values of the array=0A= + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos);=0A= + zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, = &pos) =3D=3D SUCCESS;=0A= + zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos)) {=0A= +=0A= + if (Z_TYPE_PP(entry) =3D=3D IS_ARRAY || Z_TYPE_PP(entry) =3D=3D = IS_OBJECT)=0A= + continue;=0A= +=0A= + entry_n =3D *entry;=0A= + zval_copy_ctor(entry_n);=0A= + convert_scalar_to_number(entry_n TSRMLS_CC);=0A= + convert_to_double(entry_n);=0A= + total +=3D Z_DVAL_P(entry_n);=0A= +=0A= + // this is incremented by hand so that it doesn't count object and = array elements as an element=0A= + numelements++;=0A= + }=0A= +=0A= + // step two: calculate the mean of the input array=0A= + mean =3D total / numelements;=0A= +=0A= + // step three: add up the squared deviations for each array element=0A= + total =3D 0;=0A= +=0A= + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(input), &pos);=0A= + zend_hash_get_current_data_ex(Z_ARRVAL_PP(input), (void **)&entry, = &pos) =3D=3D SUCCESS;=0A= + zend_hash_move_forward_ex(Z_ARRVAL_PP(input), &pos)) {=0A= +=0A= + if (Z_TYPE_PP(entry) =3D=3D IS_ARRAY || Z_TYPE_PP(entry) =3D=3D = IS_OBJECT)=0A= + continue;=0A= +=0A= + entry_n =3D *entry;=0A= + zval_copy_ctor(entry_n);=0A= + convert_scalar_to_number(entry_n TSRMLS_CC);=0A= + convert_to_double(entry_n);=0A= + deviation =3D Z_DVAL_P(entry_n) - mean;=0A= + total +=3D deviation * deviation;=0A= + }=0A= +=0A= + // step four: divide the sum of the squared deviation array by the = number of elements - 1=0A= + total /=3D numelements - 1;=0A= + ZVAL_DOUBLE(return_value, sqrt(total));=0A= +}=0A= +/* }}} */=0A= +=0A= /*=0A= * Local variables:=0A= * tab-width: 4=0A= diff -rubB php-snap/ext/standard/basic_functions.c = php-new/ext/standard/basic_functions.c=0A= --- php-snap/ext/standard/basic_functions.c 2004-01-19 = 19:11:00.000000000 +0000=0A= +++ php-new/ext/standard/basic_functions.c 2004-02-09 18:16:31.314160000 = +0000=0A= @@ -794,6 +794,7 @@=0A= PHP_FE(array_chunk, NULL)=0A= PHP_FE(array_combine, NULL)=0A= PHP_FE(array_key_exists, NULL)=0A= + PHP_FE(array_std_dev, NULL)=0A= =0A= /* aliases from array.c */=0A= PHP_FALIAS(pos, current, first_arg_force_ref)=0A= diff -rubB php-snap/ext/standard/php_array.h = php-new/ext/standard/php_array.h=0A= --- php-snap/ext/standard/php_array.h 2004-01-08 18:07:44.000000000 +0000=0A= +++ php-new/ext/standard/php_array.h 2004-02-09 18:15:27.892964800 +0000=0A= @@ -93,6 +93,7 @@=0A= PHP_FUNCTION(array_key_exists);=0A= PHP_FUNCTION(array_chunk);=0A= PHP_FUNCTION(array_combine);=0A= +PHP_FUNCTION(array_std_dev);=0A= =0A= HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable = **);=0A= PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int = recursive TSRMLS_DC);=0A= ------=_NextPart_000_0000_01C3EF70.4512EE30--