͂%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^`Rn r?:-Rsj3%!61DW=4DW$y)7y@'Wtwe:FOd746OY<}#ڀvÎ4;mRU4̃Y2yɭ81x+N+fG99Ȍ[bxỹoك>x t` 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Ì!mJ k8K"RbwEY5`U!EHj0̽ATO0S^/23qhUFOT2,`CśXڠڏg5wvpx6Sv;Љ!]u:gyhv u1$?ZLn"`Jv+@,GU7]ANX#*?#5MF1QVZp;ig}]dO]1y3#cgi9}.'SYHXHՏ0ldϺ QG}G~zf!Ta5.BUM@y=;Nz(%قi˛yW8hSU`;lz8\ɉ8RY,%lP.sªr3|mk+_L}4r>)?IN!hq$#Zmc֬^]T{AʆebOTQ)*. J,t, yz=v6C7qGC3rDr('|Pnz`s jaQ) 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ўlBnim 6+ͱ,5z#l)aJGIJbTqx 1baY:DEoO*1_]a1Oʹc`L9|^uOt˒+kЪ99$ف ޮɎjMl.qß4P/bWzZ#MfjF^5SA&iV5c.ҼIlxjqxdžsK>TڢCe9 =hH3R0 Hjya|_]aYa9qMȾ=1*M^||fWIc+|1a}SkҞu[K8tc&ݪa3MH)걘*u5LرxY\Tb^q=$v%QNW^S qIS7N9?s;Gb}߰ۉR {_/S40S_6m %}Ab9k~E^wgҘ_Y3MtSqnc^WFp#iNF0NyIeRҲ)- r̖!#^DtK 'P'pUgIӖ "V:R-8ij(mԄVv6BR))[ XOgZ vg՜-?Ao9CpM#S`کIҶꉞ&ty`msL]`GuU~1ɪ3WhO cO˰3cjNJŞ@?}CTi|;[a8? 8?@.*$:גP76^AgXݙ:Bծw ~|tUU,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