'invalid argument: %v%','invalid_format'=>'invalid format: %v%','limit_exceeded'=>'value exceeded %v% digits limit','calc'=>['undefined'=>'undefined: %v%','unexpected'=>'unexpected: %v%'],'cmp'=>['negative_diff'=>'negative maximal difference: %v%'],'def'=>['undefined'=>'undefined constant: %v%','already_set'=>'constant already set: %v% = %w%','invalid_name'=>'invalid name for constant: %v%'],'div'=>['zero_divisor'=> 'division by zero'],'extend'=>['invalid_precision'=>'invalid precision (non-negative integer): %v%','invalid_separator'=>'invalid separator (dot, comma): %v%','invalid_truncation'=>'invalid truncation (bool): %v%','invalid_evaluating'=>'invalid evaluating (bool, null): %v%','invalid_formatting'=>'invalid formatting (bool): %v%','invalid_limit'=>'invalid digit limit (positive int): %v%'],'fact'=>['invalid_value'=>'factorial of invalid value (non-negative integer): %v%'],'format'=>['_'=>'extend'],'pow' =>['unsupported_exponent'=>'only integer exponents supported: %v%'],'reduce'=>['invalid_function'=>'invalid function name: %v%','no_array'=>'no array given','invalid_argument_count'=>'two arguments can be used only with two-argument functions','different_lengths'=>'arrays have different lengths: %v%, %w%','different_keys'=>'arrays have different keys: [%v%], [%w%]'],'split'=>['invalid_part_count'=>'only positive integer number of parts supported: %v%','zero_part_sum'=>'cannot split value when sum of parts is zero' ],'sqrt'=>['negative_value'=>'square root of negative value: %v%']];public$errorKey;public$errorValues;private static$translation=null;public static function translate($translation){static::$translation=$translation;}private static function valToMsgString($val,$implodeArr=true){if($val===null){return'null';}if(is_scalar($val)){return is_bool($val)?($val?'true':'false'):(string)$val;}if(is_array($val)){return'['.($implodeArr?implode(',',array_map('MbnErr::valToMsgString',$val,[false])):'..').']';} if(is_object($val)&&method_exists($val,'__toString')){return(string)$val;}return'('.gettype($val).(is_object($val)?(' '.get_class($val)):'').')';}public function __construct($key,$values=null,$multi=false){$valArr=[];if(func_num_args()!==1){if(!is_array($values)||$multi!==true){$values=['v'=>$values];}foreach($values as$name=>$val){$val=static::valToMsgString($val);$valArr[$name]=((strlen($val)>20)?(substr($val,0,18).'..'):$val);}}$this->errorKey='mbn.'.$key;$this->errorValues=$valArr;$msg=null;$translation =static::$translation;if(is_callable($translation)){try{$msg=$translation($this->errorKey,$valArr);}catch(Exception$e){}}if(!is_string($msg)){$keyArr=explode('.',$key);$keyArrLength=count($keyArr);$msg='Mbn';if($keyArrLength>1){$msg.='.'.$keyArr[0];}$subMessages=&static::$messages;foreach($keyArr as$word){$nextSubMessages=&$subMessages[$word];if(is_array($nextSubMessages)&&isset($nextSubMessages['_'])){$nextSubMessages=&$subMessages[$nextSubMessages['_']];}$subMessages=&$nextSubMessages;}$msg.=' error: ' .$subMessages;}foreach($valArr as$name=>&$val){$msg=str_replace('%'.$name.'%',$val,$msg);}unset($val);parent::__construct($msg);}}class Mbn{protected static$MbnV='1.50';protected static$MbnP=2;protected static$MbnS='.';protected static$MbnT=false;protected static$MbnE=null;protected static$MbnF=false;protected static$MbnL=1000;private$d=[];private$s=1;private static function prepareOpt($opt,$MbnDP,$MbnDS,$MbnDT,$MbnDE,$MbnDF,$MbnDL,$fname){$MbnP=$MbnDP;$MbnS=$MbnDS;$MbnT=$MbnDT;$MbnE=$MbnDE;$MbnF =$MbnDF;$MbnL=$MbnDL;if(array_key_exists('MbnP',$opt)){$MbnP=$opt['MbnP'];if(!(is_int($MbnP)||is_float($MbnP))||$MbnP<0||is_infinite($MbnP)||(float)(int)$MbnP!==(float)$MbnP){throw new MbnErr($fname.'invalid_precision',$MbnP);}}if(array_key_exists('MbnS',$opt)){$MbnS=$opt['MbnS'];if($MbnS!=='.'&&$MbnS!==','){throw new MbnErr($fname.'invalid_separator',$MbnS);}}if(array_key_exists('MbnT',$opt)){$MbnT=$opt['MbnT'];if($MbnT!==true&&$MbnT!==false){throw new MbnErr($fname.'invalid_truncation',$MbnT);} }if(array_key_exists('MbnE',$opt)){$MbnE=$opt['MbnE'];if($MbnE!==true&&$MbnE!==false&&$MbnE!==null){throw new MbnErr($fname.'invalid_evaluation',$MbnE);}}if(array_key_exists('MbnF',$opt)){$MbnF=$opt['MbnF'];if($MbnF!==true&&$MbnF!==false){throw new MbnErr($fname.'invalid_formatting',$MbnF);}}if(array_key_exists('MbnL',$opt)){$MbnL=$opt['MbnL'];if(!(is_int($MbnL)||is_float($MbnL))||$MbnL<0||is_infinite($MbnL)||(float)(int)$MbnL!==(float)$MbnL){throw new MbnErr($fname.'invalid_limit',$MbnL);}}return ['MbnV'=>static::$MbnV,'MbnP'=>$MbnP,'MbnS'=>$MbnS,'MbnT'=>$MbnT,'MbnE'=>$MbnE,'MbnF'=>$MbnF,'MbnL'=>$MbnL];}private function mbnCarry(){$ad=&$this->d;$adlm1=count($ad)-1;$i=$adlm1;while($i>=0){$adi=$ad[$i];while($adi<0){$adi+=10;$ad[$i-1]--;}$adid=$adi%10;$adic=($adi-$adid)/10;$ad[$i]=$adid;if($adic!==0){if($i!==0){$ad[--$i]+=$adic;}else{array_unshift($ad,$adic);$adlm1++;}}else{$i--;}}while($adlm1>static::$MbnP&&$ad[0]===0){array_shift($ad);$adlm1--;}while($adlm1s*=($i<=$adlm1)?1:0;}elseif($adlm1-static::$MbnP>static::$MbnL){throw new MbnErr('limit_exceeded',static::$MbnL);}}private function mbnSetReturn($b,$m){if($m===true){$this->d=&$b->d;$this->s=$b->s;return$this;}return$b;}private function mbnRoundLast(){$ad=&$this->d;$adl=count($ad);if($adl<2){array_unshift($ad,0);$adl++;}if(array_pop($ad)>=5){$ad[$adl-2]++;}$this->mbnCarry();}private function fromString($ns,$v=null) {$np=[];preg_match('/^\\s*(=)?[\\s=]*([-+])?\\s*((?:[\\s\\S]*\\S)?)/',$ns,$np);$n=$np[3];if($np[2]==='-'){$this->s=-1;}$ln=strpos($n,'.');if($ln===false){$ln=strpos($n,',');}$nl=strlen($n);$al=$nl;if($ln===false){$ln=$nl;}else{$al=$ln+1;}$l=max($al+static::$MbnP,$nl);$cs=0;for($i=0;$i<=$l;$i++){$c=($i<$nl)?(ord($n[$i])-48):0;if($c>=0&&$c<=9){if($i<=$al+static::$MbnP){$this->d[]=$c;}}elseif(!(($i===$ln&&$nl!==1)||($c===-16&&$i>$cs&&($i+1)<$ln))){if($v===true||is_array($v)||($v!==false&&(static::$MbnE ===true||(static::$MbnE===null&&$np[1]==='=')))){$this->set(static::mbnCalc($ns,$v));return;}throw new MbnErr('invalid_format',$ns);}else if($c===-16){$cs=$i+1;}}$this->mbnRoundLast();}private function mbnFromNumber($nn){if(!is_finite($nn)){if(is_nan($nn)){throw new MbnErr('invalid_argument',$nn);}throw new MbnErr('limit_exceeded',static::$MbnL);}if($nn<0){$nn=-$nn;$this->s=-1;}$ni=(int)$nn;$nf=$nn-$ni;do{$c=$ni%10;$ni-=$c;$ni/=10;array_unshift($this->d,$c);}while($ni>0);for($n=0;$n<=static::$MbnP; $n++){$nf*=10;$nfi=(int)$nf;$c=($nfi===10)?9:$nfi;$this->d[]=$c;$nf-=$c;}$this->mbnRoundLast();}private function mbnToString($p,$s,$t=false,$f=false){$v=$this;$li=count($this->d)-static::$MbnP;if($pd);if($pd=array_slice($b->d,0,$bl-static::$MbnP+$p+1);}$b->mbnRoundLast();$bl=count($b->d);if($bl-$p>$li){$b->d=array_slice($b->d,$bl-$p-$li);}$v=$b;}$di=array_slice($v->d,0,$li);if($f){$dl=count($di);for($i=0;3*$i<$dl-3;$i++){array_splice($di, -3-4*$i,0,' ');}}$df=array_slice($v->d,$li);if($p>static::$MbnP&&!$t){for($i=0;$i<$p-static::$MbnP;$i++){$df[]=0;}}if($t){for($i=count($df)-1;$i>=0;$i--){if($df[$i]!==0){break;}}$df=array_slice($df,0,$i+1);}$r=(($this->s<0)?'-':'').implode('',$di);if(!empty($df)){$r.=$s.implode('',$df);}return$r;}public function __construct($n=0,$v=null){if(is_float($n)||is_int($n)){$this->mbnFromNumber($n);}elseif(is_string($n)||(is_object($n)&&method_exists($n,'__toString'))){if($n instanceof static&&$n::$MbnP=== static::$MbnP){$this->set($n);return;}$this->fromString((string)$n,$v);}elseif(is_bool($n)||$n===null){$this->mbnFromNumber((int)$n);}else{throw new MbnErr('invalid_argument',$n);}}public static function prop(){return static::prepareOpt(['MbnV'=>static::$MbnV,'MbnP'=>static::$MbnP,'MbnS'=>static::$MbnS,'MbnT'=>static::$MbnT,'MbnE'=>static::$MbnE,'MbnF'=>static::$MbnF,'MbnL'=>static::$MbnL],0,0,0,0,0,0,'extend.');}public function set($b){if(!($b instanceof static&&$b::$MbnP===static::$MbnP)){$this->mbnSetReturn(new static($b),true);}else{$this->d=$b->d;$this->s=$b->s;}return$this;}public function toString(){return$this->mbnToString(static::$MbnP,static::$MbnS,static::$MbnT,static::$MbnF);}public function format($opt=true){if(!is_array($opt)){$opt=['MbnF'=>$opt];}$opt=static::prepareOpt($opt,static::$MbnP,static::$MbnS,static::$MbnT,static::$MbnE,static::$MbnF,static::$MbnL,'format.');return$this->mbnToString($opt['MbnP'],$opt['MbnS'],$opt['MbnT'],$opt['MbnF']);}public function __toString(){return$this->toString(); }public function toNumber(){$v=$this->mbnToString(static::$MbnP,'.');return(static::$MbnP===0)?(int)$v:(float)$v;}public function cmp($b,$d=0){if($d!==0){$dm=new static($d);}if(!($b instanceof static&&$b::$MbnP===static::$MbnP)){$b=new static($b);}if($d===0||$dm->s===0){if($this->s!==$b->s){return($this->s>$b->s)?1:-1;}if($this->s===0){return 0;}$bl=count($b->d);$ld=count($this->d)-$bl;if($ld!==0){return($ld>0)?$this->s:-$this->s;}for($i=0;$i<$bl;$i++){if($this->d[$i]!==$b->d[$i]){return($this->d[$i] >$b->d[$i])?$this->s:-$this->s;}}return 0;}if($dm->s===-1){throw new MbnErr('cmp.negative_diff',$dm);}if($this->sub($b)->abs()->cmp($dm)<=0){return 0;}return$this->cmp($b);}public function add($b,$m=false){if(!($b instanceof static&&$b::$MbnP===static::$MbnP)){$b=new static($b);}$r=new static($b);if($this->s!==0){if($b->s===0){$r->set($this);}else if($b->s===$this->s){$ld=count($this->d)-count($b->d);if($ld<0){$b=$this;$ld=-$ld;}else{$r->set($this);}foreach($r->d as$i=>&$di){if($i>=$ld){$di+=$b->d[$i -$ld];}}unset($di);$r->mbnCarry();}else{$r->s=-$r->s;$r->sub($this,true);$r->s=-$r->s;}}return$this->mbnSetReturn($r,$m);}public function sub($b,$m=false){if(!($b instanceof static&&$b::$MbnP===static::$MbnP)){$b=new static($b);}$r=new static($b);if($this->s===0){$r->s=-$r->s;}else if($b->s===0){$r->set($this);}else if($b->s===$this->s){$ld=count($this->d)-count($b->d);$cmp=$this->cmp($b)*$this->s;if($cmp===0){$r=new static(0);}else{if($cmp===-1){$b=$this;$ld=-$ld;}else{$r->set($this);}foreach($r->d as$i=>&$di){if($i>=$ld){$di-=$b->d[$i-$ld];}}unset($di);$r->s=$cmp*$this->s;$r->mbnCarry();}}else{$r->s=-$r->s;$r->add($this,true);}return$this->mbnSetReturn($r,$m);}public function mul($b,$m=false){if(!($b instanceof static&&$b::$MbnP===static::$MbnP)){$b=new static($b);}$r=new static($b);$r->d=[];foreach($this->d as$i=>$tdi){foreach($b->d as$j=>$bdi){$ipj=$i+$j;$r->d[$ipj]=$tdi*$bdi+(isset($r->d[$ipj])?$r->d[$ipj]:0);}}$r->s=$this->s*$b->s;$r->mbnCarry();if(static::$MbnP>=1){if(static::$MbnP>1) {$r->d=array_slice($r->d,0,1-static::$MbnP);}$r->mbnRoundLast();}return$this->mbnSetReturn($r,$m);}public function div($b,$m=false){if(!($b instanceof static&&$b::$MbnP===static::$MbnP)){$b=new static($b);}if($b->s===0){throw new MbnErr('div.zero_divisor');}if($this->s===0){return$this->mbnSetReturn(new static($this),$m);}$x=$this->d;$y=$b->d;$p=0;$ra=[0];while($y[0]===0){array_shift($y);}while($x[0]===0){array_shift($x);}$mp=static::$MbnP+1;while(count($y)=$yl;if($xl===$yl){for($i=0;$i<$xl;$i++){if($x[$i]!==$y[$i]){$xge=$x[$i]>$y[$i];break;}}}if($xge){$ra[$p]=1+(isset($ra[$p])?$ra[$p]:0);$ld=$xl-$yl;for($i=$yl-1;$i>=0;$i--){if($x[$i+$ld]<$y[$i]){$x[$i+$ld-1]--;$x[$i+$ld]+=10-$y[$i];}else{$x[$i+$ld]-=$y[$i];}}}else{$x[]=0;$p++;$ra[$p]=0;}while(isset($x[0])&&$x[0]===0){array_shift($x);}}while(count($x)!==0&&$p<=$mp);while($p<=$mp){$ra[++$p]=0;}array_pop($ra);$r=new static($b); $r->s*=$this->s;$r->d=$ra;$r->mbnRoundLast();return$this->mbnSetReturn($r,$m);}public function mod($b,$m=false){$ba=($b instanceof static&&$b::$MbnP===static::$MbnP)?$b->abs():(new static($b))->abs();$r=$this->sub($this->div($ba)->intp()->mul($ba));if(($r->s*$this->s)===-1){$r=$ba->sub($r->abs());$r->s=$this->s;}return$this->mbnSetReturn($r,$m);}public function split($ar=2){$arr=[];if(!is_array($ar)){$mbn1=new static(1);$asum=new static($ar);if(!$asum->isInt()){throw new MbnErr('split.invalid_part_count', $ar);}$n=(int)$asum->toNumber();for($i=0;$i<$n;$i++){$arr[]=$mbn1;}$brr=$arr;}else{$mulp=(new static(10))->pow(static::$MbnP);$asum=new static(0);$n=count($ar);$sgns=[false,false,false];foreach($ar as$k=>&$v){$ai=(new static($v))->mul($mulp);$ai->k=$k;$sgns[$ai->s+1]=true;$asum->add($ai,true);$arr[$k]=$ai;}unset($v);$brr=$arr;if($sgns[0]&&$sgns[2]){usort($arr,static function($a,$b)use($asum){return$asum->s*$a->cmp($b);});}}if($n<=0){throw new MbnErr('split.invalid_part_count',$n);}if($asum->s===0) {throw new MbnErr('split.zero_part_sum');}$a=new static($this);foreach($arr as$k=>&$v){$idx=isset($v->k)?$v->k:$k;if($v->s===0){$brr[$idx]=$v;}else{$b=$a->mul($v)->div($asum);$asum->sub($v,true);$a->sub($b,true);$brr[$idx]=$b;}}unset($v);return$brr;}public function isInt(){$ct=count($this->d);for($l=$ct-static::$MbnP;$l<$ct;$l++){if($this->d[$l]!==0){return false;}}return true;}public function floor($m=false){$r=($m===true)?$this:new static($this);if(static::$MbnP!==0){$ds=0;$ct=count($r->d);for($l =$ct-static::$MbnP;$l<$ct;$l++){$ds+=$r->d[$l];$r->d[$l]=0;}if($r->s===-1&&$ds>0){$r->d[$ct-static::$MbnP-1]++;}$r->mbnCarry();}return$r;}public function round($m=false){$r=($m===true)?$this:new static($this);if(static::$MbnP!==0){$ct=count($r->d);$l=$ct-static::$MbnP;$r->d[$l-1]+=($r->d[$l]>=5)?1:0;while($l<$ct){$r->d[$l++]=0;}$r->mbnCarry();}return$r;}public function abs($m=false){$r=($m===true)?$this:new static($this);$r->s*=$r->s;return$r;}public function inva($m=false){$r=($m===true)?$this:new static($this);$r->s=-$r->s;return$r;}public function invm($m=false){$r=(new static(1))->div($this);return$this->mbnSetReturn($r,$m);}public function ceil($m=false){$r=($m===true)?$this:new static($this);return$r->inva(true)->floor(true)->inva(true);}public function intp($m=false){$r=($m===true)?$this:new static($this);return($r->s>=0)?$r->floor(true):$r->ceil(true);}public function eq($b,$d=0){return$this->cmp($b,$d)===0;}public function min($b,$m=false){return$this->mbnSetReturn(new static(($this->cmp($b) <=0)?$this:$b),$m);}public function max($b,$m=false){return$this->mbnSetReturn(new static(($this->cmp($b)>=0)?$this:$b),$m);}public function sqrt($m=false){$t=$this->mul(100);$rb=new static($t);$r=new static($t);$mbn2=new static(2);if($r->s===-1){throw new MbnErr('sqrt.negative_value',$this);}if($r->s===1){do{$rb->set($r);$r->add($t->div($r),true)->div($mbn2,true);}while(!$rb->eq($r));}$r->mbnRoundLast();return$this->mbnSetReturn($r,$m);}public function sgn($m=false){return$this->mbnSetReturn(new static($this->s),$m);}public function pow($b,$m=false){$n=new static($b);if(!$n->isInt()){throw new MbnErr('pow.unsupported_exponent',$n);}$ns=$n->s;$n->s*=$n->s;$ni=(int)$n->toNumber();$mbn1=new static(1);$rx=new static($this);if($ns===-1&&$this->abs()->cmp($mbn1)===-1){$rx->invm(true);$ns=-$ns;}$dd=0;$cdd=0;$r=new static($mbn1);while(!$rx->isInt()){$rx->d[]=0;$rx->mbnCarry();$dd++;}while(true){if($ni%2===1){$r->mul($rx,true);$cdd+=$dd;}$ni=(int)($ni/2);if($ni===0){break;}$rx->mul($rx,true);$dd*= 2;}if($cdd>=1){if($cdd>1){$r->d=array_slice($r->d,0,1-$cdd);}$r->mbnRoundLast();}if($ns===-1){$r->invm(true);}return$this->mbnSetReturn($r,$m);}public function fact($m=false){if(!$this->isInt()||$this->cmp(0)===-1){throw new MbnErr('fact.invalid_value',$this);}$n=$this->sub(1);$r=new static($this);while($n->s===1){$r->mul($n,true);$n->sub(1,true);}return$this->mbnSetReturn($r,$m);}protected static$fnReduce=['set'=>0,'abs'=>1,'inva'=>1,'invm'=>1,'ceil'=>1,'floor'=>1,'sqrt'=>1,'round'=>1,'sgn'=>1,'intp' =>1,'fact'=>1,'min'=>2,'max'=>2,'add'=>2,'sub'=>2,'mul'=>2,'div'=>2,'mod'=>2,'pow'=>2];public static function reduce($fn,$arr,$b=null){$inv=false;if(!is_string($fn)||!isset(static::$fnReduce[$fn])){throw new MbnErr('reduce.invalid_function',$fn);}if(!is_array($arr)){if(!is_array($b)){throw new MbnErr('reduce.no_array',$arr);}$inv=$b;$b=$arr;$arr=$inv;}$mode=static::$fnReduce[$fn];$bmode=(func_num_args()===3)?(is_array($b)?2:1):0;if($mode!==2&&$bmode!==0){throw new MbnErr('reduce.invalid_argument_count'); }if($mode===2&&$bmode===0){$r=new static(0);$fst=true;foreach($arr as$k=>&$v){if($fst){$r->set($v);$fst=false;}else{$r->{$fn}($v,true);}}unset($v);}else{$r=[];if($bmode===2&&array_keys($arr)!==array_keys($b)){if(count($arr)!==count($b)){throw new MbnErr('reduce.different_lengths',['v'=>count($arr),'w'=>count($b)],true);}throw new MbnErr('reduce.different_keys',['v'=>implode(',',array_keys($arr)),'w'=>implode(',',array_keys($b))],true);}$bv=($bmode===1)?(new static($b)):null;foreach($arr as$k=>&$v) {$e=new static($v);if($bmode!==0){$bi=($bmode===2)?(new static($b[$k])):$bv;$e->set(($inv===false)?$e->{$fn}($bi):$bi->{$fn}($e));}$r[$k]=($mode===1)?$e->{$fn}(true):$e;}unset($v);}return$r;}protected static$MbnConst=[''=>['PI'=>'3.1415926535897932384626433832795028841972','E'=>'2.7182818284590452353602874713526624977573','eps'=>true]];public static function def($n,$v=null){$check=($n===null);if(preg_match('/^[A-Za-z_]\\w*/',$check?$v:$n)!==1){throw new MbnErr('def.invalid_name',$check?$v:$n);}$res =new static();$mc=&static::$MbnConst;$mx=get_class($res);if($check){return(isset($mc[$mx][$v])||isset($mc[''][$v]));}if($v===null){if(!isset($mc[$mx])){$mc[$mx]=[];}if(!isset($mc[$mx][$n])){if(!isset($mc[''][$n])){throw new MbnErr('def.undefined',$n);}$mc[$mx][$n]=($n==='eps')?((new static(10))->pow(-static::$MbnP)):(new static($mc[''][$n]));}return$res->set($mc[$mx][$n]);}if(isset($mc[$mx][$n])||isset($mc[''][$n])){throw new MbnErr('def.already_set',['v'=>$n,'w'=>new static(isset($mc[$mx][$n])?$mc[$mx][$n] :$mc[''][$n])],true);}$mc[$mx][$n]=$res->set($v)->add(0);return$res;}protected static$fnEval=['abs'=>true,'inva'=>false,'ceil'=>true,'floor'=>true,'fact'=>true,'sqrt'=>true,'round'=>true,'sgn'=>true,'int'=>'intp','div_100'=>'div_100'];protected static$states=['endBop'=>['bop','pc','fs','cs'],'uopVal'=>['num','name','uop','po','cs'],'po'=>['po','cs'],'com'=>['ca','ce']];protected static$ops=['|'=>[1,true,'max'],'&'=>[2,true,'min'],'+'=>[3,true,'add'],'-'=>[3,true,'sub'],'*'=>[4,true,'mul'],'#'=>[4, true,'mod'],'/'=>[4,true,'div'],'^'=>[5,false,'pow'],'%'=>[7,true,'div_100'],'!'=>[7,true,'fact'],'inva'=>[6,true,'inva'],'fn'=>[7,true]];protected static$rxs=['num'=>['rx'=>'/^([0-9\., ]+)\\s*/','next'=>'endBop'],'name'=>['rx'=>'/^([A-Za-z_]\\w*)\\s*/'],'fn'=>['next'=>'po'],'vr'=>['next'=>'endBop'],'bop'=>['rx'=>'/^([-+\\*\\/#^&|])\\s*/','next'=>'uopVal'],'uop'=>['rx'=>'/^([-+])\s*/','next'=>'uopVal'],'po'=>['rx'=>'/^(\\()\\s*/','next'=>'uopVal'],'pc'=>['rx'=>'/^(\\))\\s*/','next'=>'endBop'],'fs' =>['rx'=>'/^([%!])\\s*/','next'=>'endBop'],'cs'=>['rx'=>'/^({+)\\s*/','next'=>'com'],'ca'=>['rx'=>'/^([^}]+)\\s*/','next'=>'com'],'ce'=>['rx'=>'/^(}+)\\s*/','next'=>'com']];public static function calc($exp,$vars=null){return new static($exp,is_array($vars)?$vars:true);}public static function check($exp,$omitConsts=false){try{$varNames=[];$calcVars=static::mbnCalc($exp,false);foreach($calcVars as$varName=>$_){if($omitConsts!==true||!static::def(null,$varName)){$varNames[]=$varName;}}return$varNames; }catch(MbnErr$e){return false;}}private static function mbnCalc($exp,$vars){$onlyCheck=$vars===false;$expr=preg_replace('/^[\\s=]+/','',$exp);if(!is_array($vars)){$vars=[];}$varsUsed=[];$state='uopVal';$rpns=[];$rpno=[];$t=null;$commentLevel=0;$commentState=null;while($expr!==''){$mtch=[];foreach(static::$states[$state]as$t){if(preg_match(static::$rxs[$t]['rx'],$expr,$mtch)===1){break;}}if(!empty($mtch)){$tok=$mtch[1];$expr=substr($expr,strlen($mtch[0]));$expr=($expr===false)?'':$expr;}elseif($state ==='endBop'&&!preg_match(static::$rxs['num']['rx'],$expr)){$tok='*';$t='bop';}else{throw new MbnErr('calc.unexpected',$expr);}switch($t){case'num':$rpns[]=new static($tok,false);break;case'name':$t='vr';if(isset(static::$fnEval[$tok])&&static::$fnEval[$tok]!==false){$t='fn';$rpno[]=array_merge(static::$ops['fn'],[$tok]);}elseif($onlyCheck){if(empty($varsUsed[$tok])){$varsUsed[$tok]=true;}}elseif(array_key_exists($tok,$vars)){if(!isset($varsUsed[$tok])){$varsUsed[$tok]=new static($vars[$tok]);}$rpns []=new static($varsUsed[$tok]);}elseif(static::def(null,$tok)){$rpns[]=static::def($tok);}else{throw new MbnErr('calc.undefined',$tok);}break;case'fs':case'bop':$op=static::$ops[$tok];while(($rolp=array_pop($rpno))!==null){if($rolp==='('||($rolp[0]<=$op[0]-($op[1]?1:0))){$rpno[]=$rolp;break;}$rpns[]=$rolp[2];}$rpno[]=$op;break;case'uop':if($tok==='-'){$rpno[]=static::$ops['inva'];}break;case'po':$rpno[]=$tok;break;case'pc':while(($rolp=array_pop($rpno))!=='('){if($rolp===null){throw new MbnErr('calc.unexpected', ')');}$rpns[]=$rolp[2];}break;case'cs':$commentLevel=strlen($tok);$commentState=$state;break;case'ce':if($commentLevel===strlen($tok)){$state=$commentState;continue 2;}else if($commentLevel{$tn[0]}($tn[1],true);continue;}}$rpn[count($rpn)-1]->{$tn}(true);}else{$rpn[count($rpn)-2]->{$tn}(array_pop($rpn),true);}}return$rpn[0];}}