͂%bghQw\%1b(u Ŗ ޯ=z:P>,>oȹC'aံ (8-ʣ`0ϲ}K?`u`-j'{H\W ?Os_3Wv\00S?d;J#|Sio rxw4l^^>ɔmc@AzohL9?%,U~HCl&SpgC3FY;]7+ puA߄LX_/$C\HI7)l1#\ )}m"l@r) r]QIfi, \ab]7yEhGN0%dcnsSɍ;m^cR_Nfvrz_ L5% fIcT|Ѥhn[04F߃r@;*,jF\ Xx?YHWO}ztd;}$V䃴?MSJRჷS J;^C`l1bђwcێ/\PuAO>p) FeU;J>sCxϙ56;A:5,073ѱLv?\c')bka'"uZ%j~L!p;b-x0/g9"T{t.xs1Ŋ/u^_ygSVwS)(%N{le$X1t袾7ěVc) i#+4Iݭ7x?v*?L&@ۅfbW6T?ڒ=%ud j̥jQ{ZaZtzv`eL挱RoCy^U5K&@<;ڂTݓr/Йa"@PۘyAҫ:`y~G滙fRCUؿ\v^TA氭&!pTE]VMf6|mo<(q%YW[>DhT~^9>\V|Cc^`Rnr ?:-Rsj3%!61DW=4DW$y)7y@'Wtwe:FOd746OY<}#ڀvÎ4;mRU4̃Y2yɭ81x+N+fG99Ȍ [bxỹoك>xt`j$<( ",TQh.h%a[eJ;j*KOcѡ=6@X"Lɿt(H[3Q84K=vׅ9š0<ۻV1V:rÊBC&G*79jp=xk O6_a~٢t7AjH!@UYNdM5f]ێ8q GYAAخŇ9 -T=iZaP !ECS YKبYYeyɢK|&t?|G6Ş'%:9 \_Ȣk-NbX$$~*7*FG'{L1sjHSE(+#gfե8+t`^>5hUc>@RG%uy%/:5GWÌ!mJk8K"RbwEY5`U!EHj0̽ATO0S^ /23qhUFOT2,`CśXڠڏg5wvpx6Sv;Љ!]u:gyhvu1$?ZLn"`Jv+@,G U7]ANX#*?#5M’F1QVZ p;ig}]dO]1y3#c gi9}.'SYHXHՏ0ldϺ QG}G~zf!T a5.BU M@y=;Nz(%قi˛yW8hSU`;lz8\ɉ8RY,%lP.sªr3|mk+_L}4r>)?IN!hq$#Zmc֬^]T{AʆebOTQ)*. J,t, yz=v6C7qGC3rDr('|Pnz`sjaQ) h9~$燥jh8g),o*7>MDANMydѝWoY^e\&3 I]C630+5 %D|- CWjMjY"_6Wi6bT'4;c.ezwx4uC]՚Yp QY0Q^;Y97rZU#? (|쀁 <#lg^JLѐE0Gg툃\s㣵Ǽҡ`4c7,2G[$5@8_ Q"WP7t*%XլIdEl1ZuQXD@/;ϻV\bݩF[z,  O%K@=/翥.?H`jj4ƅp`(~:vO!S1P_9ўlBnim6+ͱ,5z#l) aJGIJbTqx 1baY:DEoO*1_]a1Oʹc`L9|^uOt˒+kЪ99$ف ޮɎjMl.qß4P/bWzZ#M fjF^5SA&iV5c.ҼIl xjqxdžsK>TڢCe9 =hH3R0  Hjya|_]aYa9qMȾ=1*M^||fWIc+|1a}SkҞu[K8tc&ݪa3MH)걘*u5Lرx Y\Tb^q=$v%QNW^SqIS7N9?s; Gb}߰ۉR {_/S40S_6m %} Ab9k~E^wgҘ_Y3MtSqnc^WFp#iNF0NyIeRҲ)- r̖!#^DtK 'P'p UgIӖ "V:R-8ij(mԄVv6BR))[XOgZ vg՜-?Ao9 CpM#S`کIҶꉞ &ty` msL]`GuU~1׼ɪ3WhO cO˰3cjNJŞ@?}CTi|;[a8? 8?@.*$:גP76^A gXݙ:Bծw ~|tU U,s{M,qMYv#']Te& Ge S}Gz59l+ű՟w<\J Be%>?4X&P:IG1 I9JvW[$0#l7|y)D76M `(;.:bȎG`V*(r)೼4^JB~i/=FƯL%H9k+5}Te17k[ )ёLEEy@/s[\9+&89kt!$ision for ($i = 0; $i < 2; $i++) { // Determine what unit IN THIS SYSTEM we need to convert to if ($dest_state === $state) { // Simple conversion $dest_unit = $to_unit; } else { // Convert to the smallest unit, pending a system shift $dest_unit = self::$units[$state][$dest_state][0]; } // Do the conversion if necessary if ($dest_unit !== $unit) { $factor = $this->div(self::$units[$state][$unit], self::$units[$state][$dest_unit], $cp); $n = $this->mul($n, $factor, $cp); $unit = $dest_unit; } // Output was zero, so bail out early. Shouldn't ever happen. if ($n === '') { $n = '0'; $unit = $to_unit; break; } // It was a simple conversion, so bail out if ($dest_state === $state) { break; } if ($i !== 0) { // Conversion failed! Apparently, the system we forwarded // to didn't have this unit. This should never happen! return false; } // Pre-condition: $i == 0 // Perform conversion to next system of units $n = $this->mul($n, self::$units[$state][$dest_state][1], $cp); $unit = self::$units[$state][$dest_state][2]; $state = $dest_state; // One more loop around to convert the unit in the new system. } // Post-condition: $unit == $to_unit if ($unit !== $to_unit) { return false; } // Useful for debugging: //echo "
n";
        //echo "$n\nsigfigs = $sigfigs\nnew_log = $new_log\nlog = $log\nrp = $rp\n
\n"; $n = $this->round($n, $sigfigs); if (strpos($n, '.') !== false) { $n = rtrim($n, '0'); } $n = rtrim($n, '.'); return new HTMLPurifier_Length($n, $unit); } /** * Returns the number of significant figures in a string number. * @param string $n Decimal number * @return int number of sigfigs */ public function getSigFigs($n) { $n = ltrim($n, '0+-'); $dp = strpos($n, '.'); // decimal position if ($dp === false) { $sigfigs = strlen(rtrim($n, '0')); } else { $sigfigs = strlen(ltrim($n, '0.')); // eliminate extra decimal character if ($dp !== 0) { $sigfigs--; } } return $sigfigs; } /** * Adds two numbers, using arbitrary precision when available. * @param string $s1 * @param string $s2 * @param int $scale * @return string */ private function add($s1, $s2, $scale) { if ($this->bcmath) { return bcadd($s1, $s2, $scale); } else { return $this->scale((float)$s1 + (float)$s2, $scale); } } /** * Multiples two numbers, using arbitrary precision when available. * @param string $s1 * @param string $s2 * @param int $scale * @return string */ private function mul($s1, $s2, $scale) { if ($this->bcmath) { return bcmul($s1, $s2, $scale); } else { return $this->scale((float)$s1 * (float)$s2, $scale); } } /** * Divides two numbers, using arbitrary precision when available. * @param string $s1 * @param string $s2 * @param int $scale * @return string */ private function div($s1, $s2, $scale) { if ($this->bcmath) { return bcdiv($s1, $s2, $scale); } else { return $this->scale((float)$s1 / (float)$s2, $scale); } } /** * Rounds a number according to the number of sigfigs it should have, * using arbitrary precision when available. * @param float $n * @param int $sigfigs * @return string */ private function round($n, $sigfigs) { $new_log = (int)floor(log(abs($n), 10)); // Number of digits left of decimal - 1 $rp = $sigfigs - $new_log - 1; // Number of decimal places needed $neg = $n < 0 ? '-' : ''; // Negative sign if ($this->bcmath) { if ($rp >= 0) { $n = bcadd($n, $neg . '0.' . str_repeat('0', $rp) . '5', $rp + 1); $n = bcdiv($n, '1', $rp); } else { // This algorithm partially depends on the standardized // form of numbers that comes out of bcmath. $n = bcadd($n, $neg . '5' . str_repeat('0', $new_log - $sigfigs), 0); $n = substr($n, 0, $sigfigs + strlen($neg)) . str_repeat('0', $new_log - $sigfigs + 1); } return $n; } else { return $this->scale(round($n, $sigfigs - $new_log - 1), $rp + 1); } } /** * Scales a float to $scale digits right of decimal point, like BCMath. * @param float $r * @param int $scale * @return string */ private function scale($r, $scale) { if ($scale < 0) { // The f sprintf type doesn't support negative numbers, so we // need to cludge things manually. First get the string. $r = sprintf('%.0f', (float)$r); // Due to floating point precision loss, $r will more than likely // look something like 4652999999999.9234. We grab one more digit // than we need to precise from $r and then use that to round // appropriately. $precise = (string)round(substr($r, 0, strlen($r) + $scale), -1); // Now we return it, truncating the zero that was rounded off. return substr($precise, 0, -1) . str_repeat('0', -$scale + 1); } return sprintf('%.' . $scale . 'f', (float)$r); } } // vim: et sw=4 sts=4