PageRenderTime 74ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/assessment/macros.php

https://github.com/xiongchiamiov/IMathAS
PHP | 2318 lines | 2171 code | 64 blank | 83 comment | 355 complexity | 3567ac3b6e55cc03ea76356575efc90d MD5 | raw file
  1. <?php
  2. //IMathAS: Core randomizers and display macros
  3. //(c) 2006 David Lippman
  4. array_push($allowedmacros,"exp","sec","csc","cot","sech","csch","coth","rand","rrand","rands","rrands","randfrom","randsfrom","jointrandfrom","diffrandsfrom","nonzerorand","nonzerorrand","nonzerorands","nonzerorrands","diffrands","diffrrands","nonzerodiffrands","nonzerodiffrrands","singleshuffle","jointshuffle","makepretty","makeprettydisp","showplot","addlabel","showarrays","horizshowarrays","showasciisvg","listtoarray","arraytolist","calclisttoarray","sortarray","consecutive","gcd","lcm","calconarray","mergearrays","sumarray","dispreducedfraction","diffarrays","intersectarrays","joinarray","unionarrays","count","polymakepretty","polymakeprettydisp","makexpretty","makexprettydisp","calconarrayif","in_array","prettyint","prettyreal","arraystodots","subarray","showdataarray","arraystodoteqns","array_flip","arrayfindindex","fillarray","array_reverse","root");
  5. array_push($allowedmacros,"numtowords","randname","randmalename","randfemalename","randnames","randmalenames","randfemalenames","randcity","randcities","prettytime","definefunc","evalfunc","safepow","arrayfindindices","stringtoarray","strtoupper","strtolower","ucfirst","makereducedfraction","stringappend","stringprepend","textonimage","addplotborder","addlabelabs","makescinot","today","numtoroman","sprintf","arrayhasduplicates","addfractionaxislabels","decimaltofraction","ifthen","multicalconarray","htmlentities","formhoverover","formpopup","connectthedots","jointsort","stringpos","stringlen","stringclean","substr","makexxpretty","makexxprettydisp","forminlinebutton");
  6. function mergearrays($a,$b) {
  7. if (!is_array($a)) {
  8. $a = array($a);
  9. }
  10. if (!is_array($b)) {
  11. $b = array($b);
  12. }
  13. return array_merge($a,$b);
  14. }
  15. function arrayfindindex($n,$h) {
  16. return array_search($n,$h);
  17. }
  18. function arrayfindindices($n,$h) {
  19. return array_keys($h,$n);
  20. }
  21. function stringlen($str) {
  22. return strlen($str);
  23. }
  24. function stringpos($n,$h) {
  25. $p = strpos($h,$n);
  26. if ($p===false) {
  27. $p = -1;
  28. }
  29. return $p;
  30. }
  31. function stringclean($str,$mode=0) {
  32. switch($mode) {
  33. case 0: return trim($str); break;
  34. case 1: return preg_replace('/\s/','',$str); break;
  35. case 2: return preg_replace('/\W/','',$str); break;
  36. }
  37. }
  38. function stringtoarray($str) {
  39. $str_array=array();
  40. $len=strlen($str);
  41. for($i=0;$i<$len;$i++) {$str_array[]=$str{$i};}
  42. return $str_array;
  43. }
  44. function jointsort() {
  45. $in = func_get_args();
  46. if (count($in)<2 || !is_array($in[0]) || !is_array($in[1])) {
  47. echo "jointsort needs at least two input arrays";
  48. return array();
  49. }
  50. $a = array_shift($in);
  51. asort($a);
  52. $out = array();
  53. foreach ($a as $k=>$v) {
  54. for($i=0;$i<count($in);$i++) {
  55. $out[$i][] = $in[$i][$k];
  56. }
  57. }
  58. array_unshift($out,$a);
  59. return $out;
  60. }
  61. //$funcs can be a string or an array of strings. Each string should have format:
  62. //"function,color,xmin,xmax,startmarker,endmarker,strokewidth,strokedash"
  63. //not all entries are required. To skip middle ones, leave them empty
  64. function showplot($funcs) { //optional arguments: $xmin,$xmax,$ymin,$ymax,labels,grid,width,height
  65. if (!is_array($funcs)) {
  66. settype($funcs,"array");
  67. }
  68. $settings = array(-5,5,-5,5,1,1,200,200);
  69. for ($i = 1; $i < func_num_args(); $i++) {
  70. $settings[$i-1] = func_get_arg($i);
  71. }
  72. $ymin = $settings[2];
  73. $ymax = $settings[3];
  74. $noyaxis = false;
  75. if ($ymin==0 && $ymax==0) {
  76. $ymin = -0.5;
  77. $ymax = 0.5;
  78. $noyaxis = true;
  79. $settings[2] = -0.5;
  80. $settings[3] = 0.5;
  81. }
  82. $xxmin = $settings[0] - 5*($settings[1] - $settings[0])/$settings[6];
  83. $xxmax = $settings[1] + 5*($settings[1] - $settings[0])/$settings[6];
  84. $yymin = $settings[2] - 5*($settings[3] - $settings[2])/$settings[7];
  85. $yymax = $settings[3] + 5*($settings[3] - $settings[2])/$settings[7];
  86. $yminauto = false;
  87. $ymaxauto = false;
  88. if (substr($ymin,0,4)=='auto') {
  89. $yminauto = true;
  90. if (strpos($ymin,':')!==false) {
  91. $ypts = explode(':',$ymin);
  92. $ymin = $ypts[1];
  93. } else {
  94. $ymin = -5;
  95. }
  96. }
  97. if (substr($ymax,0,4)=='auto') {
  98. $ymaxauto = true;
  99. if (strpos($ymax,':')!==false) {
  100. $ypts = explode(':',$ymax);
  101. $ymax = $ypts[1];
  102. } else {
  103. $ymax = 5;
  104. }
  105. }
  106. //$commands = "setBorder(5); initPicture({$settings[0]},{$settings[1]},{$settings[2]},{$settings[3]});";
  107. //$alt = "Graph, window x {$settings[0]} to {$settings[1]}, y {$settings[2]} to {$settings[3]}.";
  108. $commands = '';
  109. $alt = '';
  110. if (strpos($settings[4],':')) {
  111. $settings[4] = str_replace(array('(',')'),'',$settings[4]);
  112. $lbl = explode(':',$settings[4]);
  113. }
  114. if (is_numeric($settings[4]) && $settings[4]>0) {
  115. $commands .= 'axes('.$settings[4].','.$settings[4].',1';
  116. } else if (isset($lbl[0]) && is_numeric($lbl[0]) && $lbl[0]>0 && $lbl[1]>0) {
  117. if (!isset($lbl[2])) { //allow xscl:yscl:off for ticks but no labels
  118. $commands .= 'axes('.$lbl[0].','.$lbl[1].',1';
  119. } else {
  120. $commands .= 'axes('.$lbl[0].','.$lbl[1].',null';
  121. }
  122. } else {
  123. $commands .= 'axes(1,1,null';
  124. }
  125. if (strpos($settings[5],':')) {
  126. $settings[5] = str_replace(array('(',')'),'',$settings[5]);
  127. $grid = explode(':',$settings[5]);
  128. }
  129. if (is_numeric($settings[5]) && $settings[5]>0) {
  130. $commands .= ','.$settings[5].','.$settings[5];
  131. } else if (isset($grid[0]) && is_numeric($grid[0]) && $grid[0]>0 && $grid[1]>0) {
  132. $commands .= ','.$grid[0].','.$grid[1];
  133. } else {
  134. $commands .= ',0,0';
  135. //$commands .= ');';
  136. }
  137. if ($noyaxis==true) {
  138. $commands .= ',1,0);';
  139. } else {
  140. $commands .= ');';
  141. }
  142. $absymin = 1E10;
  143. $absymax = -1E10;
  144. foreach ($funcs as $function) {
  145. if ($function=='') { continue;}
  146. $alt .= "Start Graph";
  147. $function = explode(",",$function);
  148. //correct for parametric
  149. $isparametric = false;
  150. $isineq = false;
  151. $isxequals = false;
  152. if ($function[0]{0}=='[') { //strpos($function[0],"[")===0) {
  153. $isparametric = true;
  154. $xfunc = makepretty(str_replace("[","",$function[0]));
  155. $xfunc = mathphp($xfunc,"t");
  156. $xfunc = str_replace("(t)",'($t)',$xfunc);
  157. $yfunc = makepretty(str_replace("]","",$function[1]));
  158. $yfunc = mathphp($yfunc,"t");
  159. $yfunc = str_replace("(t)",'($t)',$yfunc);
  160. array_shift($function);
  161. $evalxfunc = create_function('$t','return('.$xfunc.');');
  162. $evalyfunc = create_function('$t','return('.$yfunc.');');
  163. } else if ($function[0]{0}=='<' || $function[0]{0}=='>') {
  164. $isineq = true;
  165. if ($function[0]{1}=='=') {
  166. $ineqtype = substr($function[0],0,2);
  167. $func = makepretty(substr($function[0],2));
  168. } else {
  169. $ineqtype = $function[0]{0};
  170. $func = makepretty(substr($function[0],1));
  171. }
  172. $func = mathphp($func,"x");
  173. $func = str_replace("(x)",'($x)',$func);
  174. $evalfunc = create_function('$x','return('.$func.');');
  175. } else if (strlen($function[0])>1 && $function[0]{0}=='x' && ($function[0]{1}=='<' || $function[0]{1}=='>' || $function[0]{1}=='=')) {
  176. $isxequals = true;
  177. if ($function[0]{1}=='=') {
  178. $val = substr($function[0],2);
  179. } else {
  180. $isineq = true;
  181. if ($function[0]{2}=='=') {
  182. $ineqtype = substr($function[0],1,2);
  183. $val= substr($function[0],3);
  184. } else {
  185. $ineqtype = $function[0]{1};
  186. $val = substr($function[0],2);
  187. }
  188. }
  189. } else {
  190. $func = makepretty($function[0]);
  191. $func = mathphp($func,"x");
  192. $func = str_replace("(x)",'($x)',$func);
  193. $evalfunc = create_function('$x','return('.$func.');');
  194. }
  195. //even though ASCIIsvg has a plot function, we'll calculate it here to hide the function
  196. $path = '';
  197. if (isset($function[1]) && $function[1]!='') {
  198. $path .= "stroke=\"{$function[1]}\";";
  199. $alt .= ", Color {$function[1]}";
  200. } else {
  201. $path .= "stroke=\"black\";";
  202. $alt .= ", Color black";
  203. }
  204. if (isset($function[6]) && $function[6]!='') {
  205. $path .= "strokewidth=\"{$function[6]}\";";
  206. } else {
  207. $path .= "strokewidth=\"1\";";
  208. }
  209. if ($isineq && strlen($ineqtype)==1) { //is < or >
  210. $path .= "strokedasharray=\"5\";";
  211. $alt .= ", Dashed";
  212. } else if (isset($function[7]) && $function[7]!='') {
  213. if ($function[7]=="dash") {
  214. $path .= "strokedasharray=\"5\";";
  215. $alt .= ", Dashed";
  216. } else {
  217. $path .= "strokedasharray=\"none\";";
  218. }
  219. } else {
  220. $path .= "strokedasharray=\"none\";";
  221. }
  222. $path .= "fill=\"none\";";
  223. if ($isxequals) { //handle x-equals case separately
  224. $alt .= "<table class=stats><thead><tr><th>x</th><th>y</th></thead></tr><tbody>";
  225. $alt .= "<tr><td>$val</td><td>$ymin</td></tr>";
  226. $alt .= "<tr><td>$val</td><td>$ymax</td></tr>";
  227. $alt .= '</tbody></table>';
  228. $path .= "line([$val,$ymin],[$val,$ymax]);";
  229. $path .= "stroke=\"none\";strokedasharray=\"none\";";
  230. if ($function[1]=='red' || $function[1]=='green') {
  231. $path .= "fill=\"trans{$function[1]}\";";
  232. } else {
  233. $path .= "fill=\"transblue\";";
  234. }
  235. if ($isineq) {
  236. if ($ineqtype{0}=='<') {
  237. $path .= "rect([$xxmin,$yymin],[$val,$yymax]);";
  238. $alt .= "Shaded left";
  239. } else {
  240. $path .= "rect([$val,$yymin],[$xxmax,$yymax]);";
  241. $alt .= "Shaded right";
  242. }
  243. }
  244. $commands .= $path;
  245. continue;
  246. }
  247. $avoid = array();
  248. $domainlimited = false;
  249. if (isset($function[2]) && $function[2]!='') {
  250. $xmin = $function[2];
  251. $domainlimited = true;
  252. } else {$xmin = $settings[0];}
  253. if (isset($function[3]) && $function[3]!='') {
  254. $xmaxarr = explode('!',$function[3]);
  255. $xmax = $xmaxarr[0];
  256. $avoid = array_slice($xmaxarr,1);
  257. $domainlimited = true;
  258. } else {$xmax = $settings[1];}
  259. if ($GLOBALS['sessiondata']['graphdisp']==0) {
  260. $dx = 1;
  261. $alt .= "<table class=stats><thead><tr><th>x</th><th>y</th></thead></tr><tbody>";
  262. $stopat = ($xmax-$xmin)+1;
  263. } else {
  264. $dx = ($xmax - $xmin + ($domainlimited?0:10*($xmax-$xmin)/$settings[6]) )/100;
  265. $stopat = ($domainlimited?101:102);
  266. if ($xmax==$xmin) {
  267. $stopat = 1;
  268. }
  269. }
  270. $lasty = 0;
  271. $lastl = 0;
  272. $px = null;
  273. $py = null;
  274. $pathstr = '';
  275. $firstpoint = false;
  276. for ($i = 0; $i<$stopat;$i++) {
  277. if ($isparametric) {
  278. $t = $xmin + $dx*$i + 1E-10;
  279. if (in_array($t,$avoid)) { continue;}
  280. $x = round($evalxfunc($t),3);//round(eval("return ($xfunc);"),3);
  281. $y = round($evalyfunc($t),3);//round(eval("return ($yfunc);"),3);
  282. $alt .= "<tr><td>$x</td><td>$y</td></tr>";
  283. } else {
  284. $x = $xmin + $dx*$i + 1E-10 - ($domainlimited?0:5*($xmax-$xmin)/$settings[6]);
  285. if (in_array($x,$avoid)) { continue;}
  286. //echo $func.'<br/>';
  287. $y = round($evalfunc($x),3);//round(eval("return ($func);"),3);
  288. $alt .= "<tr><td>".($xmin + $dx*$i)."</td><td>$y</td></tr>";
  289. }
  290. if (isNaN($y)) {
  291. continue;
  292. }
  293. if ($py===null) { //starting line
  294. } else if ($y>$ymax || $y<$ymin) { //going or still out of bounds
  295. if ($py <= $ymax && $py >= $ymin) { //going out
  296. if ($y>$ymax) { //going up
  297. $iy = $ymax + 5*($ymax-$ymin)/$settings[7];
  298. } else { //going down
  299. $iy = $ymin - 5*($ymax-$ymin)/$settings[7];
  300. }
  301. $ix = ($x-$px)*($iy - $py)/($y-$py) + $px;
  302. if ($lastl == 0) {$pathstr .= "path([";} else { $pathstr .= ",";}
  303. $pathstr .= "[$px,$py],[$ix,$iy]]);";
  304. $lastl = 0;
  305. } else { //still out
  306. }
  307. } else if ($py>$ymax || $py<$ymin) { //coming or staying in bounds?
  308. if ($y <= $ymax && $y >= $ymin) { //coming in
  309. if ($py>$ymax) { //going up
  310. $iy = $ymax + 5*($ymax-$ymin)/$settings[7];
  311. } else { //going down
  312. $iy = $ymin - 5*($ymax-$ymin)/$settings[7];
  313. }
  314. $ix = ($x-$px)*($iy - $py)/($y-$py) + $px;
  315. if ($lastl == 0) {$pathstr .= "path([";} else { $pathstr .= ",";}
  316. $pathstr .= "[$ix,$iy]";
  317. $lastl++;
  318. } else { //still out
  319. }
  320. } else {//all in
  321. if ($lastl == 0) {$pathstr .= "path([";} else { $pathstr .= ",";}
  322. $pathstr .= "[$px,$py]";
  323. $lastl++;
  324. }
  325. $px = $x;
  326. $py = $y;
  327. /*if (abs($y-$lasty) > ($ymax-$ymin)) {
  328. if ($lastl > 1) { $pathstr .= ']);'; $lastl = 0;}
  329. $lasty = $y;
  330. } else {
  331. if ($lastl == 0) {$pathstr .= "path([";} else { $pathstr .= ",";}
  332. $pathstr .= "[$x,$y]";
  333. $lasty = $y;
  334. $lastl++;
  335. if ($y<$absymin) {
  336. $absymin = $y;
  337. }
  338. if ($y>$absymax) {
  339. $absymax = $y;
  340. }
  341. }
  342. */
  343. }
  344. if ($lastl > 0) {$pathstr .= "]);";}
  345. $path .= $pathstr;
  346. $alt .= "</tbody></table>\n";
  347. if ($isineq) {
  348. $pathstr = substr($pathstr,0,-3);
  349. preg_match('/^path\(\[\[(-?[\d\.]+),(-?[\d\.]+).*(-?[\d\.]+),(-?[\d\.]+)\]$/',$pathstr,$matches);
  350. $sig = ($xxmax-$xxmin)/100;
  351. $ymid = ($yymax + $yymin)/2;
  352. if ($ineqtype{0}=='<') {
  353. if (abs($matches[3] - $xxmax)>$sig && $matches[4]>$ymid) {
  354. $pathstr .= ",[$xxmax,$yymax]"; //need to add upper right corner
  355. }
  356. $pathstr .= ",[$xxmax,$yymin],[$xxmin,$yymin]";
  357. if (abs($matches[1] - $xxmin)>$sig && $matches[2]>$ymid) {
  358. $pathstr .= ",[$xxmin,$yymax]"; //need to add upper left corner
  359. }
  360. $pathstr .= ']);';
  361. } else {
  362. if (abs($matches[3] - $xxmax)>$sig && $matches[4]<$ymid) {
  363. $pathstr .= ",[$xxmax,$yymin]"; //need to add lower right corner
  364. }
  365. $pathstr .= ",[$xxmax,$yymax],[$xxmin,$yymax]";
  366. if (abs($matches[1] - $xxmin)>$sig && $matches[2]<$ymid) {
  367. $pathstr .= ",[$xxmin,$yymin]"; //need to add lower left corner
  368. }
  369. $pathstr .= ']);';
  370. }
  371. if ($function[1]=='red' || $function[1]=='green') {
  372. $path .= "fill=\"trans{$function[1]}\";";
  373. } else {
  374. $path .= "fill=\"transblue\";";
  375. }
  376. $path .= "stroke=\"none\";strokedasharray=\"none\";$pathstr";
  377. }
  378. if (isset($function[5]) && $function[5]=='open') {
  379. $path .= "dot([$x,$y],\"open\");";
  380. $alt .= "Open dot at $x,$y";
  381. } else if (isset($function[5]) && $function[5]=='closed') {
  382. $path .= "dot([$x,$y],\"closed\");";
  383. $alt .= "Closed dot at $x,$y";
  384. }
  385. if (isset($function[4]) && $function[4]=='open') {
  386. if ($isparametric) {
  387. $t = $xmin;
  388. $x = round(eval("return ($xfunc);"),3);
  389. $y = round(eval("return ($yfunc);"),3);
  390. } else {
  391. $x = $xmin; $y = round(eval("return ($func);"),4);
  392. }
  393. $path .= "dot([$x,$y],\"open\");";
  394. if ($y<$absymin) {
  395. $absymin = $y;
  396. }
  397. if ($y>$absymax) {
  398. $absymax = $y;
  399. }
  400. $alt .= "Open dot at $x,$y";
  401. } else if (isset($function[4]) && $function[4]=='closed') {
  402. if ($isparametric) {
  403. $t = $xmin;
  404. $x = round(eval("return ($xfunc);"),3);
  405. $y = round(eval("return ($yfunc);"),3);
  406. } else {
  407. $x = $xmin; $y = round(eval("return ($func);"),4);
  408. }
  409. $path .= "dot([$x,$y],\"closed\");";
  410. if ($y<$absymin) {
  411. $absymin = $y;
  412. }
  413. if ($y>$absymax) {
  414. $absymax = $y;
  415. }
  416. $alt .= "Closed dot at $x,$y";
  417. }
  418. $commands .= $path;
  419. }
  420. if ($yminauto) {
  421. $settings[2] = max($absymin,$ymin);
  422. }
  423. if ($ymaxauto) {
  424. $settings[3] = min($absymax,$ymax);
  425. }
  426. $commands = "setBorder(5); initPicture({$settings[0]},{$settings[1]},{$settings[2]},{$settings[3]});".$commands;
  427. $alt = "Graph, window x {$settings[0]} to {$settings[1]}, y {$settings[2]} to {$settings[3]}.".$alt;
  428. if ($GLOBALS['sessiondata']['graphdisp']==0) {
  429. return $alt;
  430. } else {
  431. return "<embed type='image/svg+xml' align='middle' width='$settings[6]' height='$settings[7]' src='{$GLOBALS['imasroot']}/javascript/d.svg' script='$commands' />\n";
  432. }
  433. }
  434. function addplotborder($plot,$left,$bottom=5,$right=5,$top=5) {
  435. return str_replace("setBorder(5)","setBorder($left,$bottom,$right,$top)",$plot);
  436. }
  437. function addlabel($plot,$x,$y,$lbl) {
  438. if (func_num_args()>4) {
  439. $color = func_get_arg(4);
  440. } else {
  441. $color = "black";
  442. }
  443. if (func_num_args()>6) {
  444. $loc = func_get_arg(5);
  445. $angle = func_get_arg(6);
  446. $plot = str_replace("' />","fontfill=\"$color\";text([$x,$y],\"$lbl\",\"$loc\",\"$angle\");' />",$plot);
  447. } elseif (func_num_args()>5) {
  448. $loc = func_get_arg(5);
  449. $plot = str_replace("' />","fontfill=\"$color\";text([$x,$y],\"$lbl\",\"$loc\");' />",$plot);
  450. } else {
  451. $plot = str_replace("' />","fontfill=\"$color\";text([$x,$y],\"$lbl\");' />",$plot);
  452. }
  453. return $plot;
  454. }
  455. function addlabelabs($plot,$x,$y,$lbl) {
  456. if (func_num_args()>4) {
  457. $color = func_get_arg(4);
  458. } else {
  459. $color = "black";
  460. }
  461. if (func_num_args()>6) {
  462. $loc = func_get_arg(5);
  463. $angle = func_get_arg(6);
  464. $plot = str_replace("' />","fontfill=\"$color\";textabs([$x,$y],\"$lbl\",\"$loc\",\"$angle\");' />",$plot);
  465. } elseif (func_num_args()>5) {
  466. $loc = func_get_arg(5);
  467. $plot = str_replace("' />","fontfill=\"$color\";textabs([$x,$y],\"$lbl\",\"$loc\");' />",$plot);
  468. } else {
  469. $plot = str_replace("' />","fontfill=\"$color\";textabs([$x,$y],\"$lbl\");' />",$plot);
  470. }
  471. return $plot;
  472. }
  473. function addfractionaxislabels($plot,$step) {
  474. if (strpos($step,'/')===false) {
  475. $num = $step; $den = 1;
  476. } else {
  477. list($num,$den) = explode('/',$step);
  478. }
  479. $ispi = false;
  480. if (strpos($num,'pi')!==false) {
  481. $ispi = true;
  482. $num = str_replace('pi','',$num);
  483. if ($num=='') { $num = 1;}
  484. }
  485. preg_match('/initPicture\(([\-\d\.]+),([\-\d\.]+),([\-\d\.]+),([\-\d\.]+)\)/',$plot,$matches);
  486. $xmin = $matches[1];
  487. $xmax = $matches[2];
  488. $yrange = $matches[4] - $matches[2];
  489. $stepn = $num/$den;
  490. if ($ispi) { $stepn *= M_PI;}
  491. if ($stepn==0) {echo "error: bad step size on pilabels"; return;}
  492. $step = ceil($xmin/$stepn);
  493. $totstep = ceil(($xmax-$xmin)/$stepn);
  494. $tm = -.03*$yrange;
  495. $tx = .03*$yrange;
  496. $outst = 'fontfill="black";strokewidth=0.5;stroke="black";';
  497. for ($i=0; $i<$totstep; $i++) {
  498. $x = $step*$stepn;
  499. if (abs($x)<.01) {$step++; continue;}
  500. $g = gcd($step*$num,$den);
  501. $n = ($step*$num)/$g; $d = $den/$g;
  502. if ($ispi) {
  503. if ($n==1) {
  504. $xd = '&pi;';
  505. } else if ($n==-1) {
  506. $xd = '-&pi;';
  507. } else {
  508. $xd = "$n&pi;";
  509. }
  510. } else {
  511. $xd = $n;
  512. }
  513. if ($d!=1) {$xd .= "/$d";}
  514. $outst .= "line([$x,$tm],[$x,$tx]); text([$x,0],\"$xd\",\"below\");";
  515. $step++;
  516. }
  517. return str_replace("' />","$outst' />",$plot);
  518. }
  519. function connectthedots($xarray,$yarray,$color='black',$thick=1,$startdot='',$enddot='') {
  520. if (count($xarray)!=count($yarray)) {
  521. echo "Error: x array and y array need to have the same number of elements";
  522. }
  523. $outarr = array();
  524. for ($i=1; $i<count($xarray); $i++) {
  525. if ($i==1) {$ed = $startdot;} else {$ed = '';}
  526. if ($i==count($xarray)-1) {$sd = $enddot;} else {$sd = '';}
  527. if ($xarray[$i-1]==$xarray[$i]) {
  528. //vertical line
  529. $outarr[] = "[{$xarray[$i]},t],$color,{$yarray[$i]},{$yarray[$i-1]},$sd,$ed,$thick";
  530. } else {
  531. $xd = $xarray[$i-1] - $xarray[$i];
  532. $yd = $yarray[$i-1] - $yarray[$i];
  533. $outarr[] = "[{$xarray[$i]}+t*($xd),{$yarray[$i]}+t*($yd)],$color,0,1,$sd,$ed,$thick";
  534. }
  535. }
  536. return $outarr;
  537. }
  538. function showasciisvg($script) {
  539. if (func_num_args()>2) {
  540. $width = func_get_arg(1);
  541. $height = func_get_arg(2);
  542. } else {
  543. $width = 200; $height = 200;
  544. }
  545. $script = str_replace("'",'"',$script);
  546. return "<embed type='image/svg+xml' align='middle' width='$width' height='$height' src='{$GLOBALS['imasroot']}/javascript/d.svg' script='$script' />\n";
  547. }
  548. function showarrays() {
  549. $alist = func_get_args();
  550. if (count($alist)<2) {return false;}
  551. if (count($alist)%2==1) {
  552. $format = substr($alist[count($alist)-1],0,1);
  553. }
  554. if (count($alist)<4 && is_array($alist[0])) {
  555. for ($i=0;$i<count($alist[0]);$i++) {
  556. $newalist[] = $alist[0][$i];
  557. $newalist[] = $alist[1][$i];
  558. }
  559. $alist = $newalist;
  560. }
  561. $out = '<table class=stats><thead><tr>';
  562. for ($i = 0; $i<floor(count($alist)/2); $i++) {
  563. $out .= "<th scope=\"col\">{$alist[2*$i]}</th>";
  564. }
  565. $out .= "</tr></thead><tbody>";
  566. for ($j = 0; $j<count($alist[1]); $j++) {
  567. $out .="<tr>";
  568. for ($i = 0; $i<floor(count($alist)/2); $i++) {
  569. if ($format=='c' || $format=='C') {
  570. $out .= '<td class="c">';
  571. } else if ($format=='r' || $format=='R') {
  572. $out .= '<td class="r">';
  573. } else if ($format=='l' || $format=='L') {
  574. $out .= '<td class="l">';
  575. } else {
  576. $out .= '<td>';
  577. }
  578. $out .= "{$alist[2*$i+1][$j]}</td>";
  579. }
  580. $out .="</tr>";
  581. }
  582. $out .= "</tbody></table>\n";
  583. return $out;
  584. }
  585. function horizshowarrays() {
  586. $alist = func_get_args();
  587. if (count($alist)<2) {return false;}
  588. $out = '<table class=stats>';
  589. for ($i=0; $i<count($alist)/2; $i++) {
  590. $out .= "<tr><th scope=\"row\"><b>{$alist[2*$i]}</b></th>";
  591. $out .= "<td>" . implode("</td><td>",$alist[2*$i+1]) . "</td></tr>\n";
  592. }
  593. $out .= "</tbody></table>\n";
  594. return $out;
  595. }
  596. function clean($exp) {
  597. $exp = preg_replace('/(\+|\-)\s+(\+|\-)/',"$1$2",$exp);
  598. //$exp = str_replace(" ", "", $exp); //caused problems with "x > -3"
  599. $exp = str_replace("+-","-",$exp);
  600. $exp = str_replace("-+","-",$exp);
  601. $exp = str_replace("--","+",$exp);
  602. //$exp = preg_replace('/^1\*?([a-zA-Z\(])/',"$1",$exp);
  603. //$exp = preg_replace('/([^\d\^\.])1\*?([a-zA-Z\(])/',"$1$2",$exp);
  604. return $exp;
  605. }
  606. function xclean($exp) {
  607. //goals are to cleam up 1*, 0* 0+ 0- a^0 a^1
  608. $exp = clean($exp);
  609. $exp = preg_replace('/^([a-zA-Z])\^0/','1',$exp); //x^0 -> 1
  610. $exp = preg_replace('/(\d)\*?([a-zA-Z])\^0$/',"$1",$exp); //3x^0 -> 3
  611. $exp = preg_replace('/(\d)\*?([a-zA-Z])\^0([^\d\.])/',"$1$3",$exp); //3x^0+4 -> 3+4
  612. $exp = preg_replace('/([^\d])\*?([a-zA-Z])\^0$/',"$1 1",$exp); //y*x^0 -> y*1, y+x^0 -> y+1
  613. $exp = preg_replace('/([^\d])\*?([a-zA-Z])\^0([^\d\.])/',"$1 1 $3",$exp); //y*x^0+3 -> y*1+3, y+x^0+z -> y+1+z
  614. $exp = preg_replace('/^0\s*\*?[^\+\-\.]+\+?/','',$exp); // 0*23+x
  615. $exp = preg_replace('/^0\s*([\+\-])/',"$1",$exp); //0+x, 0-x
  616. $exp = preg_replace('/[\+\-]\s*0\s*\*?[^\.\+\-]+/','',$exp); //3+0x-4 -> 3-4
  617. $exp = preg_replace('/[\+\-]\s*0\s*([\+\-])/',"$1",$exp); //3+0+4 -> 3+4
  618. $exp = preg_replace('/^1\s*\*?([a-zA-Z])/',"$1",$exp); //1x -> x
  619. $exp = preg_replace('/([^\d\^\.])1\s*\*?([a-zA-Z\(])/',"$1$2",$exp); //3+1x -> 3+x
  620. $exp = preg_replace('/\^1([^\d])/',"$1",$exp); //3x^1+4 =>3x+4
  621. $exp = preg_replace('/\^1$/','',$exp); //4x^1 -> 4x
  622. $exp = clean($exp);
  623. if ($exp{0}=='+') {
  624. $exp = substr($exp,1);
  625. }
  626. return $exp;
  627. }
  628. function polyclean($exp) {
  629. $exp = clean($exp);
  630. $i = 0;
  631. $outstr = '';
  632. $p = 0;
  633. $parr = array('','','');
  634. $onpow = false;
  635. $lastsign = '+';
  636. $exp .= '+';
  637. while ($i<strlen($exp)) {
  638. $c = $exp{$i};
  639. if (($c >='0' && $c<='9') || $c=='.' || $c=='/' || $c=='(' || $c==')') {
  640. if ($onpow) {
  641. $parr[2] .= $c;
  642. } else {
  643. $parr[0] .= $c;
  644. }
  645. } else if (($c<='z' && $c>='a') || ($c<='Z' && $c>='A')) {
  646. $parr[1] .= $c;
  647. } else if ($c=='^') {
  648. $onpow = true;
  649. } else if ($c == '+' || $c == '-') {
  650. if ($i+1<strlen($exp) && $parr[2]=='' && $onpow) {
  651. $n = $exp{$i+1};
  652. if ($c=='-' && (($n>= '0' && $n<='9') || $n=='.')) {
  653. $parr[2] .= '-';
  654. $i++;
  655. continue;
  656. }
  657. }
  658. if ($parr[0]=='0') {
  659. $parr = array('','','');
  660. $onpow = false;
  661. $i++;
  662. $lastsign = $c;
  663. continue;
  664. } else {
  665. if ($outstr!='' || $lastsign=='-') {
  666. $outstr .= $lastsign;
  667. }
  668. }
  669. if ($parr[2]=='0' || ($parr[2]=='' && $parr[1]=='')) {
  670. if ($parr[1]=='') {
  671. $outstr .= $parr[0]; // n
  672. } else {
  673. if ($parr[0] == '') {
  674. $outstr .= 1; // x^0
  675. } else {
  676. $outstr .= $parr[0]; //n x^0
  677. }
  678. }
  679. } else if ($parr[2]=='') {
  680. if ($parr[0]=='1') {
  681. $outstr .= $parr[1];
  682. } else {
  683. $outstr .= $parr[0].' '.$parr[1];
  684. }
  685. } else if ($parr[2]=='1') {
  686. if ($parr[0]=='1') {
  687. $outstr .= $parr[1];
  688. } else {
  689. $outstr .= $parr[0] . ' ' . $parr[1]; //n x^1
  690. }
  691. } else {
  692. if ($parr[0]=='1') {
  693. $outstr .= $parr[1] . '^' . $parr[2]; // 1 x^m
  694. } else {
  695. $outstr .= $parr[0] . ' ' . $parr[1] . '^' . $parr[2]; // n x^m
  696. }
  697. }
  698. $lastsign = $c;
  699. $parr = array('','','');
  700. $onpow = false;
  701. }
  702. $i++;
  703. }
  704. return $outstr;
  705. /*
  706. $exp = clean($exp);
  707. if ($exp{0}=='+') {
  708. $exp = substr($exp,1);
  709. }
  710. return $exp;
  711. */
  712. }
  713. function makepretty($exp) {
  714. if (is_array($exp)) {
  715. for ($i=0;$i<count($exp);$i++) {
  716. $exp[$i]=clean($exp[$i]);
  717. }
  718. } else {
  719. $exp = clean($exp);
  720. }
  721. return $exp;
  722. }
  723. function makexpretty($exp) {
  724. if (is_array($exp)) {
  725. for ($i=0;$i<count($exp);$i++) {
  726. $exp[$i]=xclean($exp[$i]);
  727. }
  728. } else {
  729. $exp = xclean($exp);
  730. }
  731. return $exp;
  732. }
  733. function makexxpretty($exp,$funcs=array()) {
  734. if (is_array($exp)) {
  735. for ($i=0;$i<count($exp);$i++) {
  736. $exp[$i] = clean($exp[$i]);
  737. $exp[$i]=cleanbytoken($exp[$i],$funcs);
  738. }
  739. } else {
  740. $exp = clean($exp);
  741. $exp = cleanbytoken($exp,$funcs);
  742. }
  743. return $exp;
  744. }
  745. function polymakepretty($exp) {
  746. if (is_array($exp)) {
  747. for ($i=0;$i<count($exp);$i++) {
  748. $exp[$i]=polyclean($exp[$i]);
  749. }
  750. } else {
  751. $exp = polyclean($exp);
  752. }
  753. return $exp;
  754. }
  755. function makeprettydisp($exp) {
  756. if (is_array($exp)) {
  757. for ($i=0;$i<count($exp);$i++) {
  758. $exp[$i]="`".clean($exp[$i])."`";
  759. }
  760. } else {
  761. $exp = "`".clean($exp)."`";
  762. }
  763. return $exp;
  764. }
  765. function makexprettydisp($exp) {
  766. if (is_array($exp)) {
  767. for ($i=0;$i<count($exp);$i++) {
  768. $exp[$i]="`".xclean($exp[$i])."`";
  769. }
  770. } else {
  771. $exp = "`".xclean($exp)."`";
  772. }
  773. return $exp;
  774. }
  775. function makexxprettydisp($exp,$funcs=array()) {
  776. if (is_array($exp)) {
  777. for ($i=0;$i<count($exp);$i++) {
  778. $exp[$i] = clean($exp[$i]);
  779. $exp[$i]="`".cleanbytoken($exp[$i],$funcs)."`";
  780. }
  781. } else {
  782. $exp = clean($exp);
  783. $exp = "`".cleanbytoken($exp,$funcs)."`";
  784. }
  785. return $exp;
  786. }
  787. function polymakeprettydisp($exp) {
  788. if (is_array($exp)) {
  789. for ($i=0;$i<count($exp);$i++) {
  790. $exp[$i]="`".polyclean($exp[$i])."`";
  791. }
  792. } else {
  793. $exp = "`".polyclean($exp)."`";
  794. }
  795. return $exp;
  796. }
  797. function makeprettyarray($a) {
  798. for ($i=0;$i<count($a);$i++) {
  799. $a = makepretty($a);
  800. }
  801. }
  802. function makeprettydisparray($a) {
  803. for ($i=0;$i<count($a);$i++) {
  804. $a = "`".makepretty($a)."`";
  805. }
  806. }
  807. function rrand($min,$max,$p) {
  808. if (func_num_args()!=3) { echo "rrand expects 3 arguments"; return $min;}
  809. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  810. if ($p==0) {echo "Error with rrand: need to set step size"; return false;}
  811. return($min + $p*rand(0,($max-$min)/$p));
  812. }
  813. function rands($min,$max,$n) {
  814. if (func_num_args()!=3) { echo "rands expects 3 arguments"; return $min;}
  815. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  816. for ($i = 0; $i < $n; $i++) {
  817. $r[$i] = rand($min,$max);
  818. }
  819. return $r;
  820. }
  821. function rrands($min,$max,$p,$n) {
  822. if (func_num_args()!=4) { echo "rrands expects 4 arguments"; return $min;}
  823. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  824. if ($p==0) {echo "Error with rrands: need to set step size"; return false;}
  825. for ($i = 0; $i < $n; $i++) {
  826. $r[$i] = $min + $p*rand(0,($max-$min)/$p);
  827. }
  828. return $r;
  829. }
  830. function randfrom($lst) {
  831. if (func_num_args()!=1) { echo "randfrom expects 1 argument"; return 1;}
  832. if (!is_array($lst)) {
  833. $lst = explode(",",$lst);
  834. }
  835. return $lst[rand(0,count($lst)-1)];
  836. }
  837. function randsfrom($lst,$n) {
  838. if (func_num_args()!=2) { echo "randsfrom expects 2 arguments"; return 1;}
  839. if (!is_array($lst)) {
  840. $lst = explode(",",$lst);
  841. }
  842. for ($i=0; $i<$n;$i++) {
  843. $r[$i] = $lst[rand(0,count($lst)-1)];
  844. }
  845. return $r;
  846. }
  847. function jointrandfrom($lst1,$lst2) {
  848. if (func_num_args()!=2) { echo "jointrandfrom expects 2 arguments"; return array(1,1);}
  849. if (!is_array($lst1)) {
  850. $lst1 = explode(",",$lst1);
  851. }
  852. if (!is_array($lst2)) {
  853. $lst2 = explode(",",$lst2);
  854. }
  855. $l = rand(0,min(count($lst1)-1,count($lst2)-1));
  856. return array($lst1[$l],$lst2[$l]);
  857. }
  858. function diffrandsfrom($lst,$n) {
  859. if (func_num_args()!=2) { echo "diffrandsfrom expects 2 arguments"; return array();}
  860. if (!is_array($lst)) {
  861. $lst = explode(",",$lst);
  862. }
  863. shuffle($lst);
  864. return array_slice($lst,0,$n);
  865. }
  866. function nonzerorand($min,$max) {
  867. if (func_num_args()!=2) { echo "nonzerorand expects 2 arguments"; return $min;}
  868. $min = ceil($min);
  869. $max = floor($max);
  870. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  871. if ($min==0 && $max==0) {
  872. echo "min=0, max=0 bad."; return 0;
  873. }
  874. do {
  875. $ret = rand($min,$max);
  876. } while ($ret == 0);
  877. return $ret;
  878. }
  879. function nonzerorrand($min,$max,$p) {
  880. if (func_num_args()!=3) { echo "nonzerorrand expects 3 arguments"; return $min;}
  881. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  882. if ($min==0 && $max==0) {
  883. echo "min=0, max=0 bad."; return 0;
  884. }
  885. if ($p==0) {echo "Error with nonzerorrand: need to set step size"; return false;}
  886. do {
  887. $ret = $min + $p*rand(0,($max-$min)/$p);
  888. } while (abs($ret)< 1e-14);
  889. return $ret;
  890. }
  891. function nonzerorands($min,$max,$n) {
  892. if (func_num_args()!=3) { echo "nonzerorands expects 3 arguments"; return $min;}
  893. $min = ceil($min);
  894. $max = floor($max);
  895. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  896. if ($min==0 && $max==0) {
  897. echo "min=0, max=0 bad."; return 0;
  898. }
  899. for ($i = 0; $i < $n; $i++) {
  900. do {
  901. $r[$i] = rand($min,$max);
  902. } while ($r[$i] == 0);
  903. }
  904. return $r;
  905. }
  906. function nonzerorrands($min,$max,$p,$n) {
  907. if (func_num_args()!=4) { echo "nonzerorrands expects 4 arguments"; return $min;}
  908. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  909. if ($min==0 && $max==0) {
  910. echo "min=0, max=0 bad."; return 0;
  911. }
  912. if ($p==0) {echo "Error with nonzerorrands: need to set step size"; return false;}
  913. for ($i = 0; $i < $n; $i++) {
  914. do {
  915. $r[$i] = $min + $p*rand(0,($max-$min)/$p);
  916. } while (abs($r[$i]) <1e-14);
  917. }
  918. return $r;
  919. }
  920. function diffrands($min,$max,$n) {
  921. if (func_num_args()!=3) { echo "diffrands expects 3 arguments"; return $min;}
  922. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  923. if ($n<.1*($max-$min)) {
  924. $out = array();
  925. while (count($out)<$n) {
  926. $x = rand($min,$max);
  927. if (!in_array($x,$out)) {
  928. $out[] = $x;
  929. }
  930. }
  931. return $out;
  932. } else {
  933. $r = range($min,$max);
  934. while ($n>count($r)) {
  935. $r = array_merge($r,$r);
  936. }
  937. shuffle($r);
  938. return array_slice($r,0,$n);
  939. }
  940. }
  941. function diffrrands($min,$max,$p,$n) {
  942. if (func_num_args()!=4) { echo "diffrrands expects 4 arguments"; return $min;}
  943. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  944. if ($p==0) {echo "Error with diffrrands: need to set step size"; return false;}
  945. $maxi = ($max-$min)/$p;
  946. if ($n<.1*$maxi) {
  947. $out = array();
  948. while (count($out)<$n) {
  949. $x = $min + $p*rand(0,$maxi);
  950. if (!in_array($x,$out)) {
  951. $out[] = $x;
  952. }
  953. }
  954. return $out;
  955. } else {
  956. $r = range(0,$maxi);
  957. while ($n>count($r)) {
  958. $r = array_merge($r,$r);
  959. }
  960. shuffle($r);
  961. $r = array_slice($r,0,$n);
  962. for ($i=0;$i<$n;$i++) {
  963. $r[$i] = $min+$p*$r[$i];
  964. }
  965. return $r;
  966. }
  967. }
  968. function nonzerodiffrands($min,$max,$n) {
  969. if (func_num_args()!=3) { echo "nonzerodiffrands expects 3 arguments"; return $min;}
  970. $min = ceil($min);
  971. $max = floor($max);
  972. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  973. if ($min==0 && $max==0) {
  974. echo "min=0, max=0 bad."; return 0;
  975. }
  976. if ($n<.1*($max-$min)) {
  977. $out = array();
  978. while (count($out)<$n) {
  979. $x = rand($min,$max);
  980. if ($x!=0 && !in_array($x,$out)) {
  981. $out[] = $x;
  982. }
  983. }
  984. return $out;
  985. } else {
  986. $r = range($min,$max);
  987. if ($min < 0 && $max > 0) {
  988. array_splice($r,-1*$min,1);
  989. }
  990. shuffle($r);
  991. return array_slice($r,0,$n);
  992. }
  993. }
  994. function nonzerodiffrrands($min,$max,$p,$n) {
  995. if (func_num_args()!=4) { echo "nonzerodiffrrands expects 4 arguments"; return $min;}
  996. if ($max < $min) {echo "Need min&lt;max"; return $min;}
  997. if ($p==0) {echo "Error with nonzerodiffrrands: need to set step size"; return false;}
  998. if ($min==0 && $max==0) {
  999. echo "min=0, max=0 bad."; return 0;
  1000. }
  1001. $maxi = ($max-$min)/$p;
  1002. if ($n<.1*$maxi) {
  1003. $out = array();
  1004. while (count($out)<$n) {
  1005. $x = $min + $p*rand(0,$maxi);
  1006. if (abs($x)>1e-14 && !in_array($x,$out)) {
  1007. $out[] = $x;
  1008. }
  1009. }
  1010. return $out;
  1011. } else {
  1012. $r = range(0,$maxi);
  1013. if ($min < 0 && $max > 0) {
  1014. array_splice($r,-1*$min/$p,1);
  1015. }
  1016. shuffle($r);
  1017. $r = array_slice($r,0,$n);
  1018. for ($i=0;$i<$n;$i++) {
  1019. $r[$i] = $min+$p*$r[$i];
  1020. }
  1021. return $r;
  1022. }
  1023. }
  1024. function singleshuffle($a) {
  1025. if (!is_array($a)) {
  1026. $a = explode(",",$a);
  1027. }
  1028. shuffle($a);
  1029. if (func_num_args()>1) {
  1030. return array_slice($a,0,func_get_arg(1));
  1031. } else {
  1032. return $a;
  1033. }
  1034. }
  1035. function jointshuffle($a1,$a2) { //optional third & fourth params $n1 and $n2
  1036. if (!is_array($a1)) {
  1037. $a1 = explode(",",$a1);
  1038. }
  1039. if (!is_array($a2)) {
  1040. $a2 = explode(",",$a2);
  1041. }
  1042. $r = array_rand($a1,count($a1));
  1043. shuffle($r);
  1044. for ($j=0;$j<count($r);$j++) {
  1045. $ra1[$j] = $a1[$r[$j]];
  1046. $ra2[$j] = $a2[$r[$j]];
  1047. }
  1048. if (func_num_args() > 2) {
  1049. $n=func_get_arg(2);
  1050. if (func_num_args() > 3) {$n2 = func_get_arg(3);} else {$n2 = $n;}
  1051. return array(array_slice($ra1,0,$n),array_slice($ra2,0,$n2));
  1052. } else {
  1053. return array($ra1,$ra2);
  1054. }
  1055. }
  1056. function listtoarray($l) {
  1057. if (func_num_args()>1 && ($GLOBALS['sessiondata']['isteacher'] || isset($GLOBALS['teacherid']))) {
  1058. echo "Warning: listtoarray expects one argument, more than one provided";
  1059. }
  1060. return (explode(",",$l));
  1061. }
  1062. function arraytolist($a, $sp=false) {
  1063. if ($sp) {
  1064. return (implode(', ',$a));
  1065. } else {
  1066. return (implode(',',$a));
  1067. }
  1068. }
  1069. function joinarray($a,$s) {
  1070. return (implode($s,$a));
  1071. }
  1072. function calclisttoarray($l) {
  1073. $l = explode(",",$l);
  1074. foreach ($l as $k=>$tocalc) {
  1075. eval('$l[$k] = ' . mathphp($tocalc,null).';');
  1076. }
  1077. return $l;
  1078. }
  1079. function sortarray($a) {
  1080. if (!is_array($a)) {
  1081. $a = explode(",",$a);
  1082. }
  1083. if (func_num_args()>1) {
  1084. $dir = func_get_arg(1);
  1085. }
  1086. if (isset($dir) && $dir=="rev") {
  1087. if (is_numeric($a[0])) {
  1088. rsort($a, SORT_NUMERIC);
  1089. } else {
  1090. rsort($a);
  1091. }
  1092. } else {
  1093. if (is_numeric($a[0])) {
  1094. sort($a, SORT_NUMERIC);
  1095. } else {
  1096. sort($a);
  1097. }
  1098. }
  1099. return $a;
  1100. }
  1101. function consecutive($min,$max,$step=1) {
  1102. $a = array();
  1103. if ($min<$max && $step>0) {
  1104. for ($i=$min;$i<$max+$step/100.0;$i+=$step) {
  1105. $a[] = $i;
  1106. }
  1107. } else if ($min > $max && $step < 0) {
  1108. for ($i=$min;$i>$max+$step/100.0;$i+=$step) {
  1109. $a[] = $i;
  1110. }
  1111. } else if (abs($min-$max) < .9*abs($step)) {
  1112. $a[] = $min;
  1113. } else {
  1114. echo "Invalid inputs to consecutive";
  1115. }
  1116. return $a;
  1117. }
  1118. function gcd($n,$m){ //greatest common divisor
  1119. $m = round(abs($m));
  1120. $n = round(abs($n));
  1121. if(!$m)return$n;
  1122. if(!$n)return$m;
  1123. return $m<$n?gcd($m,$n%$m):gcd($n,$m%$n);
  1124. }
  1125. function lcm($n, $m) //least common multiple
  1126. {
  1127. return round($m*($n/gcd($n,$m)));
  1128. }
  1129. function dispreducedfraction($n,$d,$dblslash=false) {
  1130. return '`'.makereducedfraction($n,$d,$dblslash).'`';
  1131. }
  1132. function makereducedfraction($n,$d,$dblslash=false) {
  1133. $g = gcd($n,$d);
  1134. $n = $n/$g;
  1135. $d = $d/$g;
  1136. if ($d<0) {
  1137. $n = $n*-1;
  1138. $d = $d*-1;
  1139. }
  1140. if ($d==1) {
  1141. return "$n";
  1142. } else {
  1143. if ($dblslash) {
  1144. return "$n//$d";
  1145. } else {
  1146. return "$n/$d";
  1147. }
  1148. }
  1149. }
  1150. //use: calconarray($a,"x^$p")
  1151. function calconarray($array,$todo) {
  1152. /*global $disallowedwords,$allowedmacros;
  1153. $todo = str_replace($disallowedwords,"",$todo);
  1154. $todo = clean($todo);
  1155. $rsnoquote = preg_replace('/"[^"]*"/','""',$todo);
  1156. $rsnoquote = preg_replace('/\'[^\']*\'/','\'\'',$rsnoquote);
  1157. if (preg_match_all('/([$\w]+)\s*\([^\)]*\)/',$rsnoquote,$funcs)) {
  1158. for ($i=0;$i<count($funcs[1]);$i++) {
  1159. if (strpos($funcs[1][$i],"$")===false) {
  1160. if (!in_array($funcs[1][$i],$allowedmacros)) {
  1161. echo "{$funcs[1][$i]} is not an allowed function<BR>\n";
  1162. return false;
  1163. }
  1164. }
  1165. }
  1166. }
  1167. */
  1168. $todo = mathphp($todo,'x',false,false);
  1169. $todo = str_replace('(x)','($x)',$todo);
  1170. return array_map(create_function('$x','return('.$todo.');'),$array);
  1171. }
  1172. function multicalconarray() {
  1173. $args = func_get_args();
  1174. $nargs = count($args);
  1175. $todo = array_shift($args);
  1176. $vars = array_shift($args);
  1177. $vars = explode(',',$vars);
  1178. if ($nargs-2 != count($vars)) {
  1179. echo "incorrect number of data arrays";
  1180. return false;
  1181. }
  1182. $todo = mathphp($todo,implode('|',$vars),false,false);
  1183. if ($todo=='0;') { return 0;}
  1184. for ($i=0;$i<count($vars);$i++) {
  1185. $todo = str_replace('('.$vars[$i].')','($'.$vars[$i].')',$todo);
  1186. }
  1187. $varlist = '$'.implode(',$',$vars);
  1188. $evalstr = "return(array_map(create_function('$varlist','return($todo);')";
  1189. $cnt = count($args[0]);
  1190. for ($i=0; $i<count($args); $i++) {
  1191. $evalstr .= ',$args['.$i.']';
  1192. if (count($args[$i])!=$cnt) {
  1193. echo "unequal element count in arrays";
  1194. return false;
  1195. }
  1196. }
  1197. $evalstr .= '));';
  1198. return eval($evalstr);
  1199. }
  1200. //use: calconarray($a,"x + .01","floor(x)==x")
  1201. function calconarrayif($array,$todo,$ifcond) {
  1202. /*global $disallowedwords,$allowedmacros;
  1203. $todo = str_replace($disallowedwords,"",$todo);
  1204. $todo = clean($todo);
  1205. $ifcond = clean($ifcond);
  1206. $rsnoquote = preg_replace('/"[^"]*"/','""',$todo);
  1207. $rsnoquote = preg_replace('/\'[^\']*\'/','\'\'',$rsnoquote);
  1208. if (preg_match_all('/([$\w]+)\s*\([^\)]*\)/',$rsnoquote,$funcs)) {
  1209. for ($i=0;$i<count($funcs[1]);$i++) {
  1210. if (strpos($funcs[1][$i],"$")===false) {
  1211. if (!in_array($funcs[1][$i],$allowedmacros)) {
  1212. echo "{$funcs[1][$i]} is not an allowed function<BR>\n";
  1213. return false;
  1214. }
  1215. }
  1216. }
  1217. }
  1218. */
  1219. $todo = mathphp($todo,'x',false,false);
  1220. $todo = str_replace('(x)','($x)',$todo);
  1221. /*
  1222. $rsnoquote = preg_replace('/"[^"]*"/','""',$ifcond);
  1223. $rsnoquote = preg_replace('/\'[^\']*\'/','\'\'',$rsnoquote);
  1224. if (preg_match_all('/([$\w]+)\s*\([^\)]*\)/',$rsnoquote,$funcs)) {
  1225. $ismath = true;
  1226. for ($i=0;$i<count($funcs[1]);$i++) {
  1227. if (strpos($funcs[1][$i],"$")===false) {
  1228. if (!in_array($funcs[1][$i],$allowedmacros)) {
  1229. echo "{$funcs[1][$i]} is not an allowed function<BR>\n";
  1230. return false;
  1231. }
  1232. }
  1233. }
  1234. }
  1235. $ifcond = str_replace('!=','#=',$ifcond);
  1236. */
  1237. $ifcond = mathphp($ifcond,'x',false,false);
  1238. //$ifcond = str_replace('#=','!=',$ifcond);
  1239. $ifcond = str_replace('(x)','($x)',$ifcond);
  1240. $iffunc = create_function('$x','return('.$ifcond.');');
  1241. $tmpfunc = create_function('$x','return('.$todo.');');
  1242. foreach($array as $k=>$x) {
  1243. if ($iffunc($x)) {
  1244. $array[$k] = $tmpfunc($x);
  1245. }
  1246. }
  1247. return $array;
  1248. }
  1249. function sumarray($array) {
  1250. return array_sum($array);
  1251. }
  1252. function intersectarrays($a1,$a2) {
  1253. return array_values(array_intersect($a1,$a2));
  1254. }
  1255. function diffarrays($a1,$a2) {
  1256. return array_values(array_diff($a1,$a2));
  1257. }
  1258. function unionarrays($a1,$a2) {
  1259. foreach ($a2 as $v) {
  1260. if (!in_array($v,$a1)) {
  1261. $a1[] = $v;
  1262. }
  1263. }
  1264. return array_values($a1);
  1265. }
  1266. function prettyint($n) {
  1267. return number_format($n);
  1268. }
  1269. function prettyreal($n,$d) {
  1270. return number_format($n,$d);
  1271. }
  1272. function makescinot($n,$d=8,$f="x") {
  1273. if ($n==0) { return "0";}
  1274. $isneg = "";
  1275. if ($n<0) { $isneg = "-"; $n = abs($n);}
  1276. $exp = floor(log10($n));
  1277. $mant = round($n/pow(10,$exp),$d);
  1278. if ($f=="*") {
  1279. return "$isneg $mant * 10^($exp)";
  1280. } else if ($f=="E") {
  1281. return "$isneg $mant E $exp";
  1282. } else {
  1283. return "$isneg $mant xx 10^($exp)";
  1284. }
  1285. }
  1286. function stringappend($v,$s) {
  1287. if (is_array($v)) {
  1288. foreach($v as $k=>$y) {
  1289. $v[$k] = $v[$k].$s;
  1290. }
  1291. } else {
  1292. $v = $v.$s;
  1293. }
  1294. return $v;
  1295. }
  1296. function stringprepend($v,$s) {
  1297. if (is_array($v)) {
  1298. foreach($v as $k=>$y) {
  1299. $v[$k] = $s.$v[$k];
  1300. }
  1301. } else {
  1302. $v = $s.$v;
  1303. }
  1304. return $v;
  1305. }
  1306. function arraystodots($x,$y) {
  1307. $out = array();
  1308. for ($i=0;$i<count($x);$i++) {
  1309. $out[] = $x[$i].','.$y[$i];
  1310. }
  1311. return $out;
  1312. }
  1313. function arraystodoteqns($x,$y,$color='blue') {
  1314. $out = array();
  1315. for ($i=0;$i<count($x);$i++) {
  1316. $out[] = $y[$i].','.$color.','.$x[$i].','.$x[$i].','.'closed';
  1317. }
  1318. return $out;
  1319. }
  1320. function subarray($a) {
  1321. if (is_array(func_get_arg(1))) {
  1322. $args = func_get_arg(1);
  1323. } else {
  1324. $args = func_get_args();
  1325. array_shift($args);
  1326. }
  1327. if (count($args)<1) {return array();}
  1328. $out = array();
  1329. for ($i=0;$i<count($args);$i++) {
  1330. if (strpos($args[$i],':')!==false) {
  1331. $p = explode(':',$args[$i]);
  1332. array_splice($out,count($out),0,array_slice($a,$p[0],$p[1]-$p[0]+1));
  1333. } else {
  1334. $out[] = $a[$args[$i]];
  1335. }
  1336. }
  1337. return $out;
  1338. }
  1339. function showdataarray($a,$n=1) {
  1340. if (!is_array($a)) {
  1341. return '';
  1342. }
  1343. $out = '<table class=stats><tbody>';
  1344. $cnt = 0;
  1345. while ($cnt<count($a)) {
  1346. $out .= '<tr>';
  1347. for ($i=0;$i<$n;$i++) {
  1348. if (isset($a[$cnt])) {
  1349. $out .= '<td>'.$a[$cnt].'</td>';
  1350. } else {
  1351. $out .= '<td></td>';
  1352. }
  1353. $cnt++;
  1354. }
  1355. $out .= '</tr>';
  1356. }
  1357. $out .= '</tbody></table>';
  1358. return $out;
  1359. }
  1360. $ones = array( "", " one", " two", " three", " four", " five", " six", " seven", " eight", " nine", " ten", " eleven", " twelve", " thirteen", " fourteen", " fifteen", " sixteen", " seventeen", " eighteen", " nineteen");
  1361. $onesth = array(""," first"," second", " third", " fourth", " fifth", " sixth", " seventh", " eighth", " ninth", "tenth"," eleventh", " twelfth", " thirteenth", " fourteenth"," fifteenth", " sixteenth", " seventeenth", " eighteenth"," nineteenth");
  1362. $tens = array( "", "", " twenty", " thirty", " forty", " fifty", " sixty", " seventy", " eighty", " ninety");
  1363. $tensth = array("","","twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth", "seventieth", "eightieth", "ninetieth");
  1364. $triplets = array( "", " thousand", " million", " billion", " trillion", " quadrillion", " quintillion", " sextillion", " septillion", " octillion", " nonillion");
  1365. $placevals = array( "", "tenth", "hundredth", "thousandth", "ten-thousandth", "hundred-thousandth", "millionth", "ten-millionth", "hundred-millionth", "billionth");
  1366. // recursive fn, converts three digits per pass
  1367. function convertTri($num, $tri, $doth=false) {
  1368. global $ones, $onesth, $tens, $tensth, $triplets;
  1369. // chunk the number, ...rxyy
  1370. $r = (int) ($num / 1000);
  1371. $x = ($num / 100) % 10;
  1372. $y = $num % 100;
  1373. // init the output string
  1374. $str = "";
  1375. // do hundreds
  1376. if ($x > 0)
  1377. $str = $ones[$x] . " hundred";
  1378. // do ones and tens
  1379. if ($y < 20) {
  1380. if ($doth && $tri==0) {
  1381. $str .= $onesth[$y];
  1382. } else {
  1383. $str .= $ones[$y];
  1384. }
  1385. } else {
  1386. if ($doth && $tri==0) {
  1387. if ($y%10==0) {
  1388. $str .= $tensth[(int) ($y / 10)];
  1389. } else {
  1390. $str .= $tens[(int) ($y / 10)] . $onesth[$y % 10];
  1391. }
  1392. } else {
  1393. $str .= $tens[(int) ($y / 10)] . $ones[$y % 10];
  1394. }
  1395. }
  1396. // add triplet modifier only if there
  1397. // is some output to be modified...
  1398. if ($str != "")
  1399. $str .= $triplets[$tri];
  1400. // continue recursing?
  1401. if ($r > 0)
  1402. return convertTri($r, $tri+1).$str;
  1403. else
  1404. return $str;
  1405. }
  1406. function numtowords($num,$doth=false) {
  1407. global $placevals;
  1408. if ($num==0) {
  1409. return "zero";
  1410. }
  1411. $int = floor($num);
  1412. $dec = $num-$int;
  1413. $out = '';
  1414. if ($int>0) {
  1415. $out .= convertTri($int,0,$doth);
  1416. if ($dec>0) {
  1417. $out .= " and ";
  1418. }
  1419. }
  1420. if ($dec>0) {
  1421. $cnt = 0;
  1422. while (abs($dec-round($dec))>1e-9 && $cnt<9) {
  1423. $dec *= 10;
  1424. $cnt++;
  1425. }
  1426. $out .= convertTri($dec,0);
  1427. $out .= ' '.$placevals[$cnt];
  1428. if ($dec!=1) {
  1429. $out .= 's';
  1430. }
  1431. }
  1432. return trim($out);
  1433. }
  1434. $namearray[0] = explode(',',"Aaron,Ahmed,Aidan,Alan,Alex,Alfonso,Andres,Andrew,Antonio,Armando,Arturo,Austin,Ben,Bill,Blake,Bradley,Brayden,Brendan,Brian,Bryce,Caleb,Cameron,Carlos,Casey,Cesar,Chad,Chance,Chase,Chris,Cody,Collin,Colton,Conner,Corey,Dakota,Damien,Danny,Darius,David,Deandre,Demetrius,Derek,Devante,Devin,Devonte,Diego,Donald,Dustin,Dylan,Eduardo,Emanuel,Enrique,Erik,Ethan,Evan,Francisco,Frank,Gabriel,Garrett,Gerardo,Gregory,Ian,Isaac,Jacob,Jaime,Jake,Jamal,James,Jared,Jason,Jeff,Jeremy,Jesse,John,Jordan,Jose,Joseph,Josh,Juan,Julian,Julio,Justin,Juwan,Keegan,Ken,Kevin,Kyle,Landon,Levi,Logan,Lucas,Luis,Malik,Manuel,Marcus,Mark,Matt,Micah,Michael,Miguel,Nate,Nick,Noah,Omar,Paul,Quinn,Randall,Ricardo,Ricky,Roberto,Roy,Russell,Ryan,Salvador,Sam,Santos,Scott,Sergio,Shane,Shaun,Skyler,Spencer,Stephen,Taylor,Tevin,Todd,Tom,Tony,Travis,Trent,Trevor,Trey,Tristan,Tyler,Wade,Warren,Wyatt,Zach");
  1435. $namearray[1] = explode(',',"Adriana,Adrianna,Alejandra,Alexandra,Alexis,Alice,Alicia,Alma,Amanda,Amber,Amy,Andrea,Angela,Anna,April,Ariana,Ashley,Ashton,Autumn,Bianca,Bria,Brianna,Brittany,Brooke,Caitlyn,Carissa,Carolyn,Carrie,Cassandra,Catherine,Chasity,Chelsea,Chloe,Christy,Ciara,Claudia,Colleen,Courtney,Cristina,Crystal,Dana,Danielle,Delaney,Destiny,Diana,Elizabeth,Emily,Emma,Erica,Erin,Esmeralda,Gabrielle,Guadalupe,Haley,Hanna,Heather,Hillary,Holly,Jacqueline,Jamie,Jane,Jasmine,Jenna,Jennifer,Jessica,Julia,Karen,Karina,Karissa,Karla,Kathryn,Katie,Kayla,Kelly,Kelsey,Kendra,Kimberly,Kori,Kristen,Kristina,Krystal,Kylie,Laura,Lauren,Leah,Linda,Lindsey,Mackenzie,Madison,Maggie,Mariah,Marissa,Megan,Melissa,Meredith,Michelle,Mikayla,Miranda,Molly,Monique,Morgan,Naomi,Natalie,Natasha,Nicole,Nina,Noelle,Paige,Patricia,Rachael,Raquel,Rebecca,Renee,Riley,Rosa,Samantha,Sarah,Savannah,Shannon,Shantel,Sierra,Sonya,Sophia,Stacy,Stephanie,Summer,Sydney,Tatiana,Taylor,Tiana,Tiffany,Valerie,Vanessa,Victoria,Vivian,Wendy,Whitney,Zoe");
  1436. $cityarray = explode(',','Los Angeles,Dallas,Houston,Atlanta,Detroit,San Francisco,Minneapolis,St. Louis,Baltimore,Pittsburg,Cincinnati,Cleveland,San Antonio,Las Vegas,Milwaukee,Oklahoma City,New Orleans,Tucson,New York City,Chicago,Philadelphia,Miami,Boston,Phoenix,Seattle,San Diego,Tampa,Denver,Portland,Sacramento,Orlando,Kansas City,Nashville,Memphis,Hartford,Salt Lake City');
  1437. function randcities($n=1) {
  1438. global $cityarray;
  1439. $c = count($cityarray);
  1440. if ($n==1) {
  1441. return $cityarray[rand(0,$c-1)];
  1442. } else {
  1443. $out = $cityarray;
  1444. shuffle($out);
  1445. return array_slice($out,0,$n);
  1446. }
  1447. }
  1448. function randcity() {
  1449. return randcities(1);
  1450. }
  1451. function randnames($n=1,$gender=2) {
  1452. global $namearray;
  1453. if ($n==1) {
  1454. if ($gender==2) {
  1455. $gender = rand(0,1);
  1456. }
  1457. return $namearray[$gender][rand(0,137)];
  1458. } else {
  1459. $out = array();
  1460. $locs = diffrands(0,137,$n);
  1461. for ($i=0; $i<$n;$i++) {
  1462. if ($gender==2) {
  1463. $gender = rand(0,1);
  1464. }
  1465. $out[] = $namearray[$gender][$locs[$i]];
  1466. }
  1467. return $out;
  1468. }
  1469. }
  1470. function randmalenames($n=1) {
  1471. return randnames($n,0);
  1472. }
  1473. function randfemalenames($n=1) {
  1474. return randnames($n,1);
  1475. }
  1476. function randname() {
  1477. return randnames(1,2);
  1478. }
  1479. function randmalename() {
  1480. return randnames(1,0);
  1481. }
  1482. function randfemalename() {
  1483. return randnames(1,1);
  1484. }
  1485. function prettytime($time,$in,$out) {
  1486. if ($in=='m') {
  1487. $time *= 60;
  1488. } else if ($in=='h') {
  1489. $time *= 60*60;
  1490. }
  1491. $hrs = $time/3600;
  1492. $min = $time/60;
  1493. $outst = '';
  1494. if (strpos($out,'clock')!==false) { //clock time
  1495. $ampm = ($hrs<12?"am":"pm");
  1496. $hrs = floor($hrs);
  1497. if ($out=='sclock') {
  1498. $min = floor($min -60*$hrs);
  1499. $sec = round($time - 60*$min - 3600*$hrs);
  1500. if ($min<10) { $min = '0'.$min;}
  1501. if ($sec<10) { $sec = '0'.$sec;}
  1502. $outst = "$hrs:$min:$sec $ampm";
  1503. } else {
  1504. $min = round($min -60*$hrs);
  1505. if ($min<10) { $min = '0'.$min;}
  1506. $outst = "$hrs:$min $ampm";
  1507. }
  1508. return $outst;
  1509. }
  1510. if (strpos($out,'h')!==false) { //has hrs
  1511. if (strpos($out,'m')!==false) { //has min
  1512. $hrs = floor($hrs);
  1513. if (strpos($out,'s')!==false) { //hrs min sec
  1514. $min = floor($min-60*$hrs);
  1515. $sec = round($time - 60*$min - 3600*$hrs,4);
  1516. $outst = "$hrs hour" . ($hrs>1 ? 's':'');
  1517. $outst .= ", $min minute" . ($min>1 ? 's':'');
  1518. $outst .= ", and $sec second" . ($sec!=1 ? 's':'');
  1519. } else { //hrs min
  1520. $min = round($min - 60*$hrs,4);
  1521. $outst = "$hrs hour" . ($hrs>1 ? 's':'');
  1522. $outst .= " and $min minute" . ($min!=1 ? 's':'');
  1523. }
  1524. } else { //no min
  1525. if (strpos($out,'s')!==false) { //hrs sec
  1526. $hrs = floor($hrs);
  1527. $sec = round($time - 3600*$hrs,4);
  1528. $outst = "$hrs hour" . ($hrs>1 ? 's':'');
  1529. $outst .= " and $sec second" . ($sec!=1 ? 's':'');
  1530. } else {//just hrs
  1531. $hrs = round($hrs,4);
  1532. $outst = "$hrs hours" . ($hrs!=1 ? 's':'');
  1533. }
  1534. }
  1535. } else { //no hours
  1536. if (strpos($out,'m')!==false) { //
  1537. if (strpos($out,'s')!==false) { //min sec
  1538. $min = floor($min);
  1539. $sec = round($time - 60*$min,4);
  1540. $outst = "$min minute" . ($min>1 ? 's':'');
  1541. $outst .= " and $sec second" . ($sec!=1 ? 's':'');
  1542. } else { //min only
  1543. $min = round($min,4);
  1544. $outst = "$min minute" . ($min!=1 ? 's':'');
  1545. }
  1546. } else if (strpos($out,'s')!==false) { //sec
  1547. $time = round($time,4);
  1548. $outst = "$time second". ($sec!=1 ? 's':'');
  1549. }
  1550. }
  1551. return $outst;
  1552. }
  1553. function definefunc($func,$varlist) {
  1554. $vars = explode(',',$varlist);
  1555. /*$toparen = implode('|',$vars);
  1556. if ($toparen != '') {
  1557. $reg = "/(" . $toparen . ")(" . $toparen . ')$/';
  1558. $func= preg_replace($reg,"($1)($2)",$func);
  1559. $reg = "/(" . $toparen . ")(sqrt|ln|log|sin|cos|tan|sec|csc|cot|abs)/";
  1560. $func= preg_replace($reg,"($1)$2",$func);
  1561. $reg = "/(" . $toparen . ")(" . $toparen . ')([^a-df-zA-Z\(])/';
  1562. $func= preg_replace($reg,"($1)($2)$3",$func);
  1563. $reg = "/([^a-zA-Z])(" . $toparen . ")([^a-zA-Z])/";
  1564. $func= preg_replace($reg,"$1($2)$3",$func);
  1565. //need second run through to catch x*x
  1566. $func= preg_replace($reg,"$1($2)$3",$func);
  1567. $reg = "/^(" . $toparen . ")([^a-zA-Z])/";
  1568. $func= preg_replace($reg,"($1)$2",$func);
  1569. $reg = "/([^a-zA-Z])(" . $toparen . ")$/";
  1570. $func= preg_replace($reg,"$1($2)",$func);
  1571. $reg = "/^(" . $toparen . ")$/";
  1572. $func= preg_replace($reg,"($1)",$func);
  1573. $reg = "/\(\((" . $toparen . ")\)\)/";
  1574. $func= preg_replace($reg,"($1)",$func);
  1575. $func= preg_replace($reg,"($1)",$func);
  1576. }
  1577. */
  1578. return array($func,$varlist);
  1579. }
  1580. function evalfunc($farr) {
  1581. $args = func_get_args();
  1582. array_shift($args);
  1583. if (is_array($farr)) {
  1584. list($func,$varlist) = $farr;
  1585. //$skipextracleanup = true;
  1586. } else {
  1587. $func = $farr;
  1588. $varlist = array_shift($args);
  1589. //$skipextracleanup = false;
  1590. }
  1591. $func = makepretty($func);
  1592. $vars = explode(',',$varlist);
  1593. if (count($vars)!=count($args)) {
  1594. echo "Number of inputs to function doesn't match number of variables";
  1595. }
  1596. $isnum = true;
  1597. for ($i=0;$i<count($args);$i++) {
  1598. if (!is_numeric($args[$i])) {
  1599. $isnum = false;
  1600. }
  1601. }
  1602. $toparen = implode('|',$vars);
  1603. if ($isnum) {
  1604. $func = mathphp($func,$toparen);
  1605. if ($func=='0;') { return 0;}
  1606. $toeval = '';
  1607. foreach ($vars as $i=>$var) {
  1608. $func = str_replace("($var)","(\$$var)",$func);
  1609. $toeval .= "\$$var = {$args[$i]};";
  1610. }
  1611. $toeval .= "\$out = $func;\n";
  1612. eval($toeval);
  1613. return $out;
  1614. } else { //just replacing
  1615. if ($toparen != '') { // && !$skipextracleanup) {
  1616. $reg = "/(" . $toparen . ")(" . $toparen . ')$/';
  1617. $func= preg_replace($reg,"($1)($2)",$func);
  1618. $reg = "/(" . $toparen . ")(sqrt|ln|log|sin|cos|tan|sec|csc|cot|abs)/";
  1619. $func= preg_replace($reg,"($1)$2",$func);
  1620. $reg = "/(" . $toparen . ")(" . $toparen . ')([^a-df-zA-Z\(])/';
  1621. $func= preg_replace($reg,"($1)($2)$3",$func);
  1622. $reg = "/([^a-zA-Z])(" . $toparen . ")([^a-zA-Z])/";
  1623. $func= preg_replace($reg,"$1($2)$3",$func);
  1624. //need second run through to catch x*x
  1625. $func= preg_replace($reg,"$1($2)$3",$func);
  1626. $reg = "/^(" . $toparen . ")([^a-zA-Z])/";
  1627. $func= preg_replace($reg,"($1)$2",$func);
  1628. $reg = "/([^a-zA-Z])(" . $toparen . ")$/";
  1629. $func= preg_replace($reg,"$1($2)",$func);
  1630. $reg = "/^(" . $toparen . ")$/";
  1631. $func= preg_replace($reg,"($1)",$func);
  1632. $reg = "/\(\((" . $toparen . ")\)\)/";
  1633. $func= preg_replace($reg,"($1)",$func);
  1634. $func= preg_replace($reg,"($1)",$func);
  1635. }
  1636. foreach ($vars as $i=>$var) {
  1637. $func = str_replace("($var)","({$args[$i]})",$func);
  1638. }
  1639. $reg = '/^\((\d*?\.?\d*?)\)([^\d\.])/';
  1640. $func= preg_replace($reg,"$1$2",$func);
  1641. $reg = '/^\(([a-zA-Z])\)([^a-zA-Z])/';
  1642. $func= preg_replace($reg,"$1$2",$func);
  1643. $reg = '/([^\d\.])\((\d*?\.?\d*?)\)$/';
  1644. $func= preg_replace($reg,"$1$2",$func);
  1645. $reg = '/([^a-zA-Z])\(([a-zA-Z])\)$/';
  1646. $func= preg_replace($reg,"$1$2",$func);
  1647. $reg = '/([^\d\.])\((\d*?\.?\d*?)\)([^\d\.])/';
  1648. $func= preg_replace($reg,"$1$2$3",$func);
  1649. $reg = '/([^a-zA-Z])\(([a-zA-Z])\)([^a-zA-Z])/';
  1650. $func= preg_replace($reg,"$1$2$3",$func);
  1651. return $func;
  1652. }
  1653. }
  1654. function textonimage() {
  1655. $args = func_get_args();
  1656. $img = array_shift($args);
  1657. $img = preg_replace('/^.*src="(.*?)".*$/',"$1",$img);
  1658. $out = '<div style="position: relative;">';
  1659. $out .= '<img src="'.$img.'" style="position: relative; top: 0px; left: 0px;" />';
  1660. while (count($args)>2) {
  1661. $text = array_shift($args);
  1662. $left = array_shift($args);
  1663. $top = array_shift($args);
  1664. $out .= "<div style=\"position: absolute; top: {$top}px; left: {$left}px;\">$text</div>";
  1665. }
  1666. $out .= '</div>';
  1667. return $out;
  1668. }
  1669. function today($str = "F j, Y") {
  1670. return (date($str));
  1671. }
  1672. function numtoroman($n,$uc=true) {
  1673. if ($uc) {
  1674. $lookup = array('M'=>1000,'CM'=>900,'D'=>500,'CD'=>400,'C'=>100,'XC'=>90,'L'=>50,'XL'=>40,'X'=>10,'IX'=>9,'V'=>5,'IV'=>4,'I'=>1,'<span style="border-top:1px solid;">SS</span>'=>0.5);
  1675. } else {
  1676. $lookup = array('m'=>1000,'cm'=>900,'d'=>500,'cd'=>400,'c'=>100,'xc'=>90,'l'=>50,'xl'=>40,'x'=>10,'ix'=>9,'v'=>5,'iv'=>4,'i'=>1,'<span style="border-top:1px solid;">ss</span>'=>0.5);
  1677. }
  1678. $roman = '';
  1679. foreach($lookup as $r=>$v) {
  1680. while($n >= $v) {
  1681. $roman .= $r;
  1682. $n -= $v;
  1683. }
  1684. }
  1685. return $roman;
  1686. }
  1687. function fillarray($v,$n,$s=0) {
  1688. return array_fill($s,$n,$v);
  1689. }
  1690. function arrayhasduplicates($arr) {
  1691. if (count($arr)==count(array_unique($arr))) {
  1692. return false;
  1693. } else {
  1694. return true;
  1695. }
  1696. }
  1697. function ifthen($c,$t,$f) {
  1698. return $c?$t:$f;
  1699. }
  1700. //adapted from http://www.mindspring.com/~alanh/fracs.html
  1701. function decimaltofraction($d,$format="fraction",$maxden = 5000) {
  1702. if (floor($d)==$d) {
  1703. return floor($d);
  1704. }
  1705. if ($d<0) {
  1706. $sign = '-';
  1707. } else {
  1708. $sign = '';
  1709. }
  1710. $d = abs($d);
  1711. $numerators = array(0, 1);
  1712. $denominators = array(1, 0);
  1713. $d2 = $d;
  1714. $calcD = -1;
  1715. $prevCalcD = -1;
  1716. for ($i = 2; $i < 1000; $i++) {
  1717. $L2 = floor($d2);
  1718. $numerators[$i] = $L2 * $numerators[$i-1] + $numerators[$i-2];
  1719. //if (Math.abs(numerators[i]) > maxNumerator) return;
  1720. $denominators[$i] = $L2 * $denominators[$i-1] + $denominators[$i-2];
  1721. if (abs($denominators[$i])>$maxden) {
  1722. break;
  1723. }
  1724. $calcD = $numerators[$i] / $denominators[$i];
  1725. if ($calcD == $prevCalcD) { break; }
  1726. //appendFractionsOutput(numerators[i], denominators[i]);
  1727. //if ($calcD == $d) { break;}
  1728. if (abs($calcD - $d)<1e-9) { break;}
  1729. $prevCalcD = $calcD;
  1730. $d2 = 1/($d2-$L2);
  1731. }
  1732. if (abs($numerators[$i]/$denominators[$i] - $d)>1e-9) {
  1733. return $d;
  1734. }
  1735. if ($format=="mixednumber") {
  1736. $w = floor($numerators[$i]/$denominators[$i]);
  1737. if ($w>0) {
  1738. $n = $numerators[$i] - $w*$denominators[$i];
  1739. return "{$sign}$w $n/".$denominators[$i];
  1740. } else {
  1741. return $sign.$numerators[$i].'/'.$denominators[$i];
  1742. }
  1743. } else {
  1744. return $sign.$numerators[$i].'/'.$denominators[$i];
  1745. }
  1746. }
  1747. function evalbasic($str) {
  1748. if (is_numeric($str)) {
  1749. return $str;
  1750. } else if (preg_match('/[^\d+\-\/\*\.]/',$str)) {
  1751. return $str;
  1752. } else {
  1753. eval("\$ret = $str;");
  1754. return $ret;
  1755. }
  1756. }
  1757. function formhoverover($label,$tip) {
  1758. if (function_exists('filter')) {
  1759. return '<span class="link" onmouseover="tipshow(this,\''.htmlentities(filter($tip),ENT_QUOTES).'\')" onmouseout="tipout()">'.$label.'</span>';
  1760. } else {
  1761. return '<span class="link" onmouseover="tipshow(this,\''.htmlentities($tip,ENT_QUOTES).'\')" onmouseout="tipout()">'.$label.'</span>';
  1762. }
  1763. }
  1764. function formpopup($label,$content,$width=600,$height=400,$type='link',$scroll='null',$id='popup') {
  1765. if ($scroll != null) {
  1766. $scroll = ','.$scroll;
  1767. }
  1768. if ($height=='fit') {
  1769. $height = "'fit'";
  1770. }
  1771. if (strpos($label,'<img')!==false) {
  1772. return str_replace('<img', '<img class="clickable" onClick="popupwindow(\''.$id.'\',\''.str_replace('\'','\\\'',htmlentities($content)).'\','.$width.','.$height.$scroll.')"',$label);
  1773. } else {
  1774. if ($type=='link') {
  1775. return '<span class="link" onClick="popupwindow(\''.$id.'\',\''.str_replace('\'','\\\'',htmlentities($content)).'\','.$width.','.$height.$scroll.')">'.$label.'</span>';
  1776. } else if ($type=='button') {
  1777. return '<span class="spanbutton" onClick="popupwindow(\''.$id.'\',\''.str_replace('\'','\\\'',htmlentities($content)).'\','.$width.','.$height.$scroll.')">'.$label.'</span>';
  1778. }
  1779. }
  1780. }
  1781. function forminlinebutton($label,$content,$style='button',$outstyle='block') {
  1782. if (isset($GLOBALS['inlinebuttoncnt'])) {
  1783. $r = $GLOBALS['inlinebuttoncnt'];
  1784. $GLOBALS['inlinebuttoncnt']++;
  1785. //$out = '';
  1786. } else {
  1787. $r = 1;
  1788. $GLOBALS['inlinebuttoncnt'] = 2;
  1789. //$out = '<script type="text/javascript">function toggleinlinebtn(n){var el=document.getElementById(n);el.style.display=="none"?el.style.display="":el.style.display="none";}</script>';
  1790. }
  1791. $label = str_replace('"','',$label);
  1792. if ($style=='classic') {
  1793. $out = '<input type="button" value="'.$label.'" onClick="toggleinlinebtn(\'inlinebtn'.$r.'\');" />';
  1794. } else if ($style=='link') {
  1795. $out = '<span class="link" onClick="toggleinlinebtn(\'inlinebtn'.$r.'\');">'.$label.'</span>';
  1796. } else {
  1797. $out = '<span class="spanbutton" onClick="toggleinlinebtn(\'inlinebtn'.$r.'\');">'.$label.'</span>';
  1798. }
  1799. if ($outstyle=='inline') {
  1800. $out .= ' <span id="inlinebtn'.$r.'" style="display:none;">'.$content.'</span>';
  1801. } else {
  1802. $out .= '<div id="inlinebtn'.$r.'" style="display:none;">'.$content.'</div>';
  1803. }
  1804. return $out;
  1805. }
  1806. function intervaltoineq($str,$var) {
  1807. if ($str=='DNE') {
  1808. return 'DNE';
  1809. }
  1810. $arr = explode('U',$str);
  1811. $out = array();
  1812. foreach ($arr as $v) {
  1813. $v = trim($v);
  1814. $sm = $v{0};
  1815. $em = $v{strlen($v)-1};
  1816. $pts = explode(',',substr($v,1,strlen($v)-2));
  1817. if ($pts[0]=='-oo') {
  1818. if ($pts[1]=='oo') {
  1819. $out[] = '"all real numbers"';
  1820. } else {
  1821. $out[] = $var . ($em==']'?'le':'lt') . $pts[1];
  1822. }
  1823. } else if ($pts[1]=='oo') {
  1824. $out[] = $var . ($sm=='['?'ge':'gt') . $pts[0];
  1825. } else {
  1826. $out[] = $pts[0] . ($sm=='['?'le':'lt') . $var . ($em==']'?'le':'lt') . $pts[1];
  1827. }
  1828. }
  1829. return implode(' \\ "or" \\ ',$out);
  1830. }
  1831. function cleanbytoken($str,$funcs = array()) {
  1832. $tokens = cleantokenize($str,$funcs);
  1833. //print_r($tokens);
  1834. $out = array();
  1835. $lasti = count($tokens)-1;
  1836. for ($i=0; $i<=$lasti; $i++) {
  1837. $token = $tokens[$i];
  1838. $lastout = count($out)-1;
  1839. if ($token[1]==3 && $token[0]==='0') { //is the number 0 by itself
  1840. if ($lastout>-1) { //if not first character
  1841. if ($out[$lastout] != '^') {
  1842. //( )0, + 0, x0
  1843. while ($lastout>-1 && $out[$lastout]!= '+' && $out[$lastout]!= '-') {
  1844. array_pop($out);
  1845. $lastout--;
  1846. }
  1847. if ($lastout>-1) {
  1848. array_pop($out);
  1849. }
  1850. } else if ($out[$lastout] == '^') {
  1851. if ($lastout>=2 && ($out[$lastout-2]=='+'|| $out[$lastout-2]=='-')) {
  1852. //4x+x^0 -> 4x+1
  1853. array_splice($out,-2);
  1854. $out[] = 1;
  1855. } else if ($lastout>=2) {
  1856. //4x^0->4, 5(x+3)^0 -> 5
  1857. array_splice($out,-2);
  1858. } else if ($lastout==1) {
  1859. //x^0 -> 1
  1860. $out = array(1);
  1861. }
  1862. }
  1863. }
  1864. if ($i<$lasti) { //if not last character
  1865. if ($tokens[$i+1][0]=='^') {
  1866. //0^3
  1867. $i+=2; //skip over ^ and 3
  1868. } else {
  1869. while ($i<$lasti && $tokens[$i+1][0]!= '+' && $tokens[$i+1][0]!= '-') {
  1870. $i++;
  1871. }
  1872. }
  1873. }
  1874. } else if ($token[1]==3 && $token[0]==='1') {
  1875. $dontuse = false;
  1876. if ($lastout>-1) { //if not first character
  1877. if ($out[$lastout] != '^' && $out[$lastout]!='+' && $out[$lastout]!='-') {
  1878. //( )1, x1,*1
  1879. if ($out[$lastout]=='*') { //elim *
  1880. array_pop($out);
  1881. }
  1882. $dontuse = true;
  1883. } else if ($out[$lastout] == '^') {
  1884. if ($lastout>=1) {
  1885. //4+x^1 -> 4+x, 4x^1 -> 4x
  1886. array_pop($out);
  1887. $dontuse = true;
  1888. }
  1889. }
  1890. }
  1891. if ($i<$lasti) { //if not last character
  1892. if ($tokens[$i+1][0]=='^') {
  1893. //1^3
  1894. $i+=2; //skip over ^ and 3
  1895. } else if ($tokens[$i+1][0]=='*') {
  1896. $i++; //skip over *
  1897. $dontuse = true;
  1898. } else if ($tokens[$i+1][0]!= '+' && $tokens[$i+1][0]!= '-' && $tokens[$i+1][0]!= '/') {
  1899. // 1x, 1(), 1sin
  1900. if ($lastout<2 || ($out[$lastout-1] != '^' || $out[$lastout] != '-')) { //exclude ^-1 case
  1901. $dontuse = true;
  1902. }
  1903. }
  1904. }
  1905. if (!$dontuse) {
  1906. $out[] = 1;
  1907. }
  1908. } else {
  1909. $out[] = $token[0];
  1910. }
  1911. }
  1912. if ($out[0]=='+') {
  1913. array_shift($out);
  1914. }
  1915. if (count($out)==0) {
  1916. return '0';
  1917. }
  1918. return implode('',$out);
  1919. }
  1920. function cleantokenize($str,$funcs) {
  1921. $knownfuncs = array_merge($funcs,array("sin","cos","sec","csc","tan","csc","cot","sinh","cosh","sech","csch","tanh","coth","arcsin","arccos","arcsec","arccsc","arctan","arccot","arcsinh","arccosh","arctanh","sqrt","ceil","floor","root","log","ln","abs","max","min"));
  1922. $lookfor = array("e","pi");
  1923. $maxvarlen = 0;
  1924. foreach ($lookfor as $v) {
  1925. $l = strlen($v);
  1926. if ($l>$maxvarlen) {
  1927. $maxvarlen = $l;
  1928. }
  1929. }
  1930. $connecttolast = 0;
  1931. $i=0;
  1932. $cnt = 0;
  1933. $len = strlen($str);
  1934. $syms = array();
  1935. $lastsym = array();
  1936. while ($i<$len) {
  1937. $cnt++;
  1938. if ($cnt>100) {
  1939. exit;
  1940. }
  1941. $intype = 0;
  1942. $out = '';
  1943. $c = $str{$i};
  1944. $eatenwhite = 0;
  1945. if ($c>="a" && $c<="z" || $c>="A" && $c<="Z") {
  1946. //is a string or function name
  1947. $intype = 2; //string like function name
  1948. do {
  1949. $out .= $c;
  1950. $i++;
  1951. if ($i==$len) {break;}
  1952. $c = $str{$i};
  1953. } while ($c>="a" && $c<="z" || $c>="A" && $c<="Z" || $c=='_'); // took out : || $c>='0' && $c<='9' don't need sin3 type function names for cleaning
  1954. //check if it's a special word
  1955. if ($out=='e') {
  1956. $intype = 3;
  1957. } else if ($out=='pi') {
  1958. $intype = 3;
  1959. } else {
  1960. //eat whitespace
  1961. while ($c==' ') {
  1962. $i++;
  1963. $c = $str{$i};
  1964. $eatenwhite++;
  1965. }
  1966. //if known function at end, strip off function
  1967. if ($c=='(' && !in_array($out,$knownfuncs)) {// moved to mathphppre-> || ($c=='^' && (substr($str,$i+1,2)=='-1' || substr($str,$i+1,4)=='(-1)'))) {
  1968. $outlen = strlen($out);
  1969. $outend = '';
  1970. for ($j=1; $j<$outlen-1; $j++) {
  1971. $outend = substr($out,$j);
  1972. if (in_array($outend,$knownfuncs)) {
  1973. $i = $i - $outlen + $j;
  1974. $c = $str{$i};
  1975. $out = substr($out,0,$j);
  1976. break;
  1977. }
  1978. }
  1979. }
  1980. //if there's a ( then it's a function if it's in our list
  1981. if ($c=='(' && $out!='e' && $out!='pi' && in_array($out,$knownfuncs)) {
  1982. //connect upcoming parens to function
  1983. $connecttolast = 2;
  1984. } else {
  1985. //is it a known function?
  1986. if (in_array($out,$knownfuncs)) {
  1987. $intype = 6;
  1988. } else {
  1989. //if not, assume it's a variable
  1990. $intype = 4;
  1991. }
  1992. }
  1993. }
  1994. } else if (($c>='0' && $c<='9') || ($c=='.' && ($str{$i+1}>='0' && $str{$i+1}<='9')) ) { //is num
  1995. $intype = 3; //number
  1996. $cont = true;
  1997. //handle . 3 which needs to act as concat
  1998. if (isset($lastsym[0]) && $lastsym[0]=='.') {
  1999. $syms[count($syms)-1][0] .= ' ';
  2000. }
  2001. do {
  2002. $out .= $c;
  2003. $lastc = $c;
  2004. $i++;
  2005. if ($i==$len) {break;}
  2006. $c= $str{$i};
  2007. if (($c>='0' && $c<='9') || ($c=='.' && $str{$i+1}!='.' && $lastc!='.')) {
  2008. //is still num
  2009. } else if ($c=='e' || $c=='E') {
  2010. //might be scientific notation: 5e6 or 3e-6
  2011. $d = $str{$i+1};
  2012. if ($d>='0' && $d<='9') {
  2013. $out .= $c;
  2014. $i++;
  2015. if ($i==$len) {break;}
  2016. $c= $str{$i};
  2017. } else if (($d=='-'||$d=='+') && ($str{$i+2}>='0' && $str{$i+2}<='9')) {
  2018. $out .= $c.$d;
  2019. $i+= 2;
  2020. if ($i>=$len) {break;}
  2021. $c= $str{$i};
  2022. } else {
  2023. $cont = false;
  2024. }
  2025. } else {
  2026. $cont = false;
  2027. }
  2028. } while ($cont);
  2029. } else if ($c=='(' || $c=='{' || $c=='[') { //parens or curlys
  2030. if ($c=='(') {
  2031. $intype = 4; //parens
  2032. $leftb = '(';
  2033. $rightb = ')';
  2034. } else if ($c=='{') {
  2035. $intype = 5; //curlys
  2036. $leftb = '{';
  2037. $rightb = '}';
  2038. } else if ($c=='[') {
  2039. $intype = 11; //array index brackets
  2040. $leftb = '[';
  2041. $rightb = ']';
  2042. }
  2043. $thisn = 1;
  2044. $inq = false;
  2045. $j = $i+1;
  2046. $len = strlen($str);
  2047. while ($j<$len) {
  2048. //read terms until we get to right bracket at same nesting level
  2049. //we have to avoid strings, as they might contain unmatched brackets
  2050. $d = $str{$j};
  2051. if ($inq) { //if inquote, leave if same marker (not escaped)
  2052. if ($d==$qtype && $str{$j-1}!='\\') {
  2053. $inq = false;
  2054. }
  2055. } else {
  2056. if ($d=='"' || $d=="'") {
  2057. $inq = true; //entering quotes
  2058. $qtype = $d;
  2059. } else if ($d==$leftb) {
  2060. $thisn++; //increase nesting depth
  2061. } else if ($d==$rightb) {
  2062. $thisn--; //decrease nesting depth
  2063. if ($thisn==0) {
  2064. //read inside of brackets, send recursively to interpreter
  2065. $inside = cleanbytoken(substr($str,$i+1,$j-$i-1), $funcs);
  2066. if ($inside=='error') {
  2067. //was an error, return error token
  2068. return array(array('',9));
  2069. }
  2070. //if curly, make sure we have a ;, unless preceeded by a $ which
  2071. //would be a variable variable
  2072. if ($rightb=='}' && $lastsym[0]!='$') {
  2073. $out .= $leftb.$inside.';'.$rightb;
  2074. } else {
  2075. $out .= $leftb.$inside.$rightb;
  2076. }
  2077. $i= $j+1;
  2078. break;
  2079. }
  2080. } else if ($d=="\n") {
  2081. //echo "unmatched parens/brackets - likely will cause an error";
  2082. }
  2083. }
  2084. $j++;
  2085. }
  2086. if ($j==$len) {
  2087. $i = $j;
  2088. echo "unmatched parens/brackets - likely will cause an error";
  2089. } else {
  2090. $c = $str{$i};
  2091. }
  2092. } else if ($c=='"' || $c=="'") { //string
  2093. $intype = 6;
  2094. $qtype = $c;
  2095. do {
  2096. $out .= $c;
  2097. $i++;
  2098. if ($i==$len) {break;}
  2099. $lastc = $c;
  2100. $c = $str{$i};
  2101. } while (!($c==$qtype && $lastc!='\\'));
  2102. $out .= $c;
  2103. $i++;
  2104. $c = $str{$i};
  2105. } else {
  2106. //no type - just append string. Could be operators
  2107. $out .= $c;
  2108. $i++;
  2109. if ($i<$len) {
  2110. $c = $str{$i};
  2111. }
  2112. }
  2113. while ($c==' ') { //eat up extra whitespace
  2114. $i++;
  2115. if ($i==$len) {break;}
  2116. $c = $str{$i};
  2117. if ($c=='.' && $intype==3) {//if 3 . needs space to act like concat
  2118. $out .= ' ';
  2119. }
  2120. }
  2121. //if parens or array index needs to be connected to func/var, do it
  2122. if ($connecttolast>0 && $intype!=$connecttolast) {
  2123. $syms[count($syms)-1][0] .= $out;
  2124. $connecttolast = 0;
  2125. if ($c=='[') {// multidim array ref?
  2126. $connecttolast = 1;
  2127. }
  2128. } else {
  2129. //add to symbol list, avoid repeat end-of-lines.
  2130. if ($intype!=7 || $lastsym[1]!=7) {
  2131. $lastsym = array($out,$intype);
  2132. $syms[] = array($out,$intype);
  2133. }
  2134. }
  2135. }
  2136. return $syms;
  2137. }
  2138. ?>