1. Paweł Wieczorek
  2. progfunproj

Commits

Paweł Wieczorek  committed 388ba4f

initial commit

  • Participants
  • Branches default

Comments (0)

Files changed (28)

File Makefile

View file
  • Ignore whitespace
+#
+# Pawel Wieczorek
+# Program rozniczkujacy funkcje jednej zmiennej
+#
+# Skrypt Makefile
+
+OCAMLC= ocamlc
+OFLAGS= -I src 
+ONAME= rozn
+SRCS=\
+     src/util.ml\
+     src/formula.ml\
+     src/yacc.ml\
+     src/lex.ml\
+     src/table0.ml\
+     src/table1.ml\
+     src/vtable0.ml\
+     src/mathtable.ml\
+     src/registry.ml\
+     src/printer.ml\
+     src/symbolsimp.ml\
+     src/symbolcalc.ml\
+     src/main.ml\
+
+
+OBJS=${SRCS:%.ml=%.cmo}
+.SUFFIXES: .ml.cmo .cmo .ml
+
+all: parser build
+
+parser:
+	@echo "lex > src/lex.mll"
+	@ocamllex src/lex.mll
+	@echo "yacc> src/yacc.mll"
+	@ocamlyacc src/yacc.mly
+
+build: ${OBJS}
+	@echo "link> ${ONAME}"
+	@${OCAMLC} -o ${ONAME} ${OBJS}
+
+.ml.cmo:
+	@if [ -f $<i ]; then ${OCAMLC} -c ${OFLAGS} $<i; echo "mli > $*"; fi
+	@echo "ml  > $*"
+	@${OCAMLC} -c ${OFLAGS} $<
+
+clean:
+	rm -f ${ONAME} src/*.cmo src/*.cmi
+

File doc/pf.pdf

  • Ignore whitespace
Binary file added.

File doc/pf.tex

View file
  • Ignore whitespace
+\documentclass[a4paper,11pt]{article}
+
+\usepackage[margin=2.5cm]{geometry}
+\usepackage[latin2]{inputenc}
+\usepackage[MeX]{polski}
+\usepackage{amsfonts}
+\usepackage{amsmath}
+
+\author{Pawe� Wieczorek}
+\title{Program r�niczkuj�cy funkcje jednej zmiennej. \\
+	{\small Projekt na pracownie z programowania funkcjonalnego. }}
+\date{\today}
+
+\begin{document}
+\maketitle
+
+\begin{abstract}
+Dokument zawiera kr�tkie om�wienie struktury programu oraz problem�w
+jakie napotka�em w jego realizacji realizacji. 
+\end{abstract}
+
+\tableofcontents
+
+\section{Reprezentacja wyra�e� matematycznych}
+
+Podstawowym zagadnieniem projektu jest reprezentacja wyra�e� matematycznych. Powinna ona by� na tyle
+elastyczna, aby mog�a opisa� dowoln� formu��, oraz na tyle prosta, aby obliczenia symboliczne wykonywane przez program
+by�y �atwe w implementacji.
+
+Poniewa� z�o�ono�� pewnych formu� mo�e przekracza� mo�liwo�ci programu postanowi�em przyj�� nast�puj�c� strategi�:
+Typ opisuj�cy wyra�enia nie posiada ogranicze� na�o�onych przez obecne mo�liwo�ci programu, jest w pewnym sensie niezale�ny.
+Dzi�ki czemu parser nie musi by� ulepszany w raz z dodaniem funkcjonalno�ci.
+
+\subsection{Definicja wyra�enia}
+
+Przyj��em nast�puj�ca definicj� formu�y matematycznej w projekcie: 
+\emph{Wyra�enie mo�e sk�ada� si� z nast�puj�cych term�w: sta�a, operator, funktor, zmienna, wyra�enie puste lub symbol stopu. Termy mog� by�
+��czone za pomoc� funktor�w i operator�w.}
+
+\[
+\mbox{type mathexpr} = \mbox{Operator(func)} \mid \mbox{Functor(func)} \mid \mbox{Const(const)} \mid \mbox{Stop(mathexpr)}
+\mid \mbox{Variable} \mid \mbox{Empty}
+\]
+
+\subsubsection{Sta�e}
+
+\emph{Za sta�� uznajemy trzy rodzaje wyra�e�: warto�� liczbowa, sta�� nazwan�, oraz
+funkcj� lub operator o niezmiennej warto�ci.}
+
+Typ sta�ej reprezentuj�cy warto�� liczbow� i sta�� nazwan�:
+\[
+	\mbox{type const} = \mbox{Value(float)} \mid \mbox{Id(char)}
+\]
+
+\subsubsection{Operatory i funktory}
+
+
+Wyra�enia matematyczne s� g��wnie funkcjami. Program do opisu funkcji u�ywa krotek otypowanych w nast�puj�cy
+spos�b:
+
+\[	\mbox{type func} = \mbox{string} \times \mbox{mathexpr}^2 \]
+
+Pierwszy element tr�jki jest napisowym identyfikatorem funktora lub operatora. 
+W programie s� dwa r�ne konstruktory u�ywaj�ce jako sw�j parametr tej krotki, s� nimi
+operatory reprezentuj�ce podstawowe operacje binarne jak i funktory opisuj�ce funckje elementerane jednej zmiennej.
+Rozr�nienie to istnieje ze wzgl�du na to, �e pochodn� operator�w binarnych liczy si� od razu, natomiast przy
+funkcjach elementarnych pojawiaj� si� z�o�enia funkcji. Takie rozwi�zanie pozwala u�ywa� pochodnej z�o�enia
+w g��wnej funkcji, nie zmuszaj�c do jego obs�ugi procesorach dotycz�cych funkcji elementarnych.
+
+W przypadku operator�w dwa ostatnie elementy krotki symbolizuj� dwa argumenty, natomiast w przypadku
+funktor�w przed ostatni jest parametrem, a ostatni argumentem. Dla przyk�adu, funkcja elementarna
+logarytm jest opisywana przez podstaw�, i to ona jest w�a�nie parametrem w przypadku tej funkcji.
+
+
+
+
+\subsubsection{Wyra�enie puste}
+
+Wyra�enie puste symbolizuje brak formu�y matematycznej w danym miejscu.
+
+
+\subsubsection{Symbol stopu}
+
+Drukowanie kolejnych przej�c przy r�niczkowaniu nie jest mozliwe bez jego zatrzymywania po ka�dym obliczeniu,
+s�u�y ku temu symbol stopu. Funkcje dokonuj�c� obliczenia r�niczkowania oznaczaj� za tego symbolu wyra�enia
+kt�re powinno zosta� przekszta�cone jako kolejny krok. Ten schemat pozwala �atwo zaimplementowa� obliczanie symboliczne
+na wz�r ``kartki z wzorami'', gdzie pochodna jakiego� wyra�enia mo�e zawiera� w sobie pochodne podwyra�e�.
+
+Dla przyk�adu, prawid�owy schemat post�powania do zr�niczkowania wyra�enia $e = \ln x + x^3$. 
+
+	\[ (\ln x + x^3)' \]
+	\[ (\ln x)' + (x^3)' \]
+	\[ \frac{1}{x} + 3x^2 \]
+
+Implementacja tego schematu w programie:
+
+	\[ (\ln x + x^3)' \]
+Wyra�enie jest opisywane przez operator dodawania, wz�r na pochodn� to $(u+v)' = u' + v'$. Po podstawieniu
+ $ (\ln x)' + (x^3)' $, poniewa� jest to krokiem obliczeniowym nale�y zatrzyma� r�niczkowanie
+i wydrukowa� obecny wynik.
+	\[ \mbox{Stop}(\ln x) + \mbox{Stop}(x^3) \]
+
+W nast�pnym kroku r�niczkowanie jest kontynuowane przez zast�pienie symbolu stopu przez
+r�niczk� wyra�enia kt�re opisuje.
+
+\subsection{Pomocnicze funkcje i wyra�enia}
+
+Definicje funkcji pomocniczych, kt�rymi b�d� si� pos�ugiwa� w dalszych cz�ciach projektu. Typy:
+
+\[ \mbox{is\_const}: \mbox{mathexpr} \rightarrow \mathbb{B} \]
+\[ \mbox{do\_multiply}: \mbox{mathexpr}^2 \rightarrow \mbox{mathexpr} \]
+\[ \mbox{do\_value}: \mathbb{R} \rightarrow \mbox{mathexpr} \]
+\[ \mbox{is\_func}: \mbox{mathexpr} \rightarrow \mathbb{B} \]
+
+Nast�puj�ca funkcja rozpoznaje wyra�enia sta�e.
+\[
+\mbox{is\_const}(e) =
+\begin{cases}
+\top & : e = \mbox{Const}(c)\\
+\mbox{is\_const}(w1) \wedge\mbox{is\_const}(w2) & : e = \mbox{Functor}\left(\langle id, w1, w2 \rangle\right)\\
+\mbox{is\_const}(w1) \wedge\mbox{is\_const}(w2) & : e = \mbox{Operator}\left(\langle id, w1, w2 \rangle\right)\\
+\bot & : p.p.
+\end{cases}
+\]
+
+Kolejna pomocnicza funkcja, pozwalaj�ce rozpoznawa� czy dane wyra�enie jest funkcj�. Jest to wyra�enie
+pomocnicze przy rozpoznawaniu z�o�e� funkcji.
+\[
+\mbox{is\_func}(e) =
+\begin{cases}
+\bot & : e = \mbox{Empty}\\
+\bot & : \mbox{is\_const}(e)\\
+\bot & : e = Variable\\
+\top & : p.p.
+\end{cases}
+\]
+
+Pomocnicze wyra�enie do ,,przejrzystego'' tworzenia operatora mno�enia.
+\[
+\mbox{do\_multiply}(e1, e2) = \begin{cases}
+\mbox{Empty} & : e1=\mbox{Empty} \vee e2=\mbox{Empty}\\
+\mbox{Operator}(\langle *, e1, e2\rangle) & : p.p.
+\end{cases}
+\]
+
+Kolejne pomocnicze wyra�enie s�u��ce jako ,,przejrzyste'' tworzenie sta�ej liczbowej.
+\[
+\mbox{do\_value}(c) = \mbox{Const(Value}(c))\\
+\]
+
+Dalsza cz�� lukru:
+\[
+	\mu(e) = \mbox{Stop}(e)
+\]
+
+
+\section{Przetwarzanie symboliczne}
+
+Zadaniem programu jest dokonywanie odpowiednich przekszta�ce� formu� matematycznych, czyli dokonywanie
+oblicze� symbolicznych. Nale�a�o wi�c zaprojektowa� t� cz�c tak, aby dodawanie kolejnych zasad przekszta�ce�,
+tzn wpis�w do tabelki z wzorami by�o niezale�ne od rdzenia aplikacji.
+
+W tym celu aplikacja posiada pewne �rodowisko wyra�e� dokonuj�cych przekszta�ce�. �rodowisko dzieli si� na dwa
+pod �rodowiska, jedne jest �rodowiskiem przekszta�ce� r�niczkuj�cych, natomiast drugie jest �rodowiskiem
+wyra�e� sprawdzaj�cych i upraszczaj�cych wyra�enia.
+
+
+
+\subsection{Przekszta�cenia}
+
+Przekszta�cenia s� wykonywane przez funkcje typu:
+\[ \mbox{processor}: \mbox{mathexpr}^2 \rightarrow \mbox{mathexpr} \]
+
+Dwoma argumentami \emph{procesora} s� dwa ostatnie elementy z krotki typu func, wyra�enie zwraca jako wynik
+dokonane przekszta�cenie. W przypadku gdy funkcja nie jest w stanie przekszta�ci� wz�r to zwraca wyra�enie puste,
+ma to na celu umo�liwienie tworzenie drobnych wyspecjalizowanych funkcji, kt�re mog� prob�wa� dokona� przekszta�cenia
+przed funkcjami og�lnymi.
+
+Przyk�adowe dwa procesory do obliczenia pochodnej operatora mno�enia, $p_1$ jest wnioskiem z og�lnego wzoru $p_0$ na temat sta�ych:
+
+\[
+	p_1(e1, e2) = \begin{cases}
+		\mbox{do\_value}(0) & : \mbox{is\_const}(e1) \wedge \mbox{is\_const}(e2)\\
+		\mbox{do\_multiply}(e1,\mu(e2)) & : \mbox{is\_const}(e1)\\
+		\mbox{do\_multiply}(e2,\mu(e1)) & : \mbox{is\_const}(e2)\\
+		\mbox{Empty} & : p.p.
+	\end{cases}
+\]
+
+\[
+	p_0(e1, e2) = \mbox{Operator}(+, \mbox{do\_multiply}(\mu(e1),e2), \mbox{do\_multiply}(e1,\mu(v2)))
+\]
+
+
+
+\subsection{�rodowisko wzor�w}
+
+�rodowisko jest prezentowane przez dwie listy wpis�w otypowanych w nast�puj�cych spos�b:
+\[
+	\mbox{type regentry} = \mbox{string} \times \mbox{processor} 
+\]
+
+Pierwszy elementem krotki jest napis b�d�cy tekstowym identyfikatorem formu�y matematycznej, z przekszta�ceniem
+kt�rej jest zwi�zany. Jedna z list �rodowiska zawiera list� dotycz�c� funktor�w a druga operator�w. 
+
+Korzystanie z �rodowiska polega na przeszukaniu rejestru w celu wy�apania wszystkich krotek zawieraj�cych
+identyfikator wyra�enia, kt�re nale�y przekszta�ci�. Nast�pnie nale�y z wszystkich znalezionych procesor�w
+zbudowa� jeden, kt�ry je warto�ciuje a� do napotkania nie zwracaj�cego wyra�enia pustego. Kolejno�c procesor�w
+w �rodowisku jest istotna, ostatnie powinny by� te u�ywaj�ce wzor�w og�lnych - bo one zawsze dokonuj� przekszta�cenia.
+
+
+
+\subsection{Metoda obliczania symbolicznego}
+
+Funkcja $\varphi: \mbox{mathexpr} \rightarrow \mbox{mathexpr}$ jest funkcja r�niczkuj�c� wyra�enie. Poniewa�
+procesory u�ywaj� znaku stopu zamiast r�niczkowa� dalej to $\varphi(e)$ mo�e by� u�yte tylko do pierwszego
+kroku przekszta�cenia. Kolejne da si� otrzyma� za pomoc� innej funkcji, kt�ra wyszukuje wyra�enia stopu
+i r�niczkuje dalej od tego miejsca (tzn zn�w dokonuje tylko pierwszego przekszta�cenia). 
+
+Funkcja jedynie rozpoznaje czy r�niczkowane wyra�enie to sta�a, je�li tak to jego r�niczka jest oczywista.
+\[
+\varphi(e) = \begin{cases}
+\mbox{do\_value}(0) & : \mbox{is\_const}(e)\\
+\hat\varphi(e) & : p.p.
+\end{cases}
+\]
+
+W przeciwnym wypadku u�ywa funkcji pomocniczej, kt�ra jest otypowana w ten sam spos�b. Jej zadanie
+polega na rozpoznaniu czym jest wyra�enie, a nast�pnie zastosowaniu wobec niego odpowiedniej strategii.
+Funkcje $\varphi_f(n,p,a)$ i $\varphi_o(n,p,a)$ s� odpowiedzialne za strategie wobec funktor�w i odpowiednio
+operator�w. R�niczka ze zmiennej jest oczywi�cie jasna i wynosi 1,0.
+\[
+\hat\varphi(e) = \begin{cases}
+	\varphi_f(n, p, a) & : e=\mbox{Functor}(\langle n, p, a\rangle)\\
+	\varphi_o(n, a, b) & : e=\mbox{Operator}(\langle n, a, b\rangle)\\
+	\mbox{do\_value}(1) & : e=\mbox{Variable}\\
+	\mbox{Stop}(\varphi(s)) & : e=\mbox{Stop}(s)\\
+	\mbox{Empty} & : p.p.
+\end{cases}
+\]
+
+Funkcja $\varphi_f(n,p,a)$ rozpoznaje, czy dany funktor - funkcja elementarna to z�o�enie
+funkcji. Je�li argument jest funkcj� to wykorzystujemy wz�r na z�o�enie. Czyli mno�ymy
+pochodn� funkcji przez pochodn� argumentu. Do zr�niczkowania funkcji jest u�ywane
+kolejne wyra�enie pomocnicze: $\hat\varphi_f(n,p,a)$, kt�re pobiera z �rodowiska
+procesor.
+
+\[
+\varphi_f(n, p, a) = \begin{cases}
+	\mbox{do\_multiply}(\hat\varphi_f(n, p, a), \mu(a)) & : \mbox{is\_func}(a)\\
+	\hat\varphi_f(n, p, a) & : p.p.
+\end{cases}
+\]
+
+\[
+\hat\varphi_f(n, p, a) = \mbox{env}_f(n)(p, a)
+\]
+
+Strategia wobec operator�w jest jasna, od razu szukamy odpowiedniego wzoru.
+\[
+\varphi_o(n, p,o) = \mbox{env}_o(n)(a, b)
+\]
+
+
+\subsection{Kontynuowanie r�niczkowania}
+
+Funkcja $\phi(e): \mbox{mathexpr} \rightarrow \mbox{mathexpr}$ jest odpowiedzialna za wygenerowanie kolejnego przej�cia, przeszukuje
+wyra�enie w celu znalezienia znaku stopu:
+
+\[
+	\phi(e) = \begin{cases}
+		\mbox{Operator}(n,\phi(a),\phi(b)) & : e=\mbox{Operator}(n,a,b)\\
+		\mbox{Functor}(n,a,\phi(p)) & : e=\mbox{Functor}(n,a,p)\\
+		\varphi(s) & : e=\mbox{Stop}(s)\\
+		e & : p.p
+	\end{cases}
+\]
+
+R�niczkowanie jest zako�czone kiedy $e = \phi(e)$, tzn kiedy nie ma ju� znak�w stopu. List� kolejnych
+przekszta�ce� �atwo otrzyma� poprzez kolejne z�o�enia tej funkcji, tzn je�li $e$ jest wyra�eniem do zr�niczkowania to:
+$\phi(\mu(e))$ jest pierwszym krokiem, $\phi^2(\mu(e))$ drugim, $\phi^3(\mu(e))$ trzecim itd.
+
+\subsection{Weryfikacja i uproszczanie}
+
+Weryfikatory pocz�tkowo mia�y slu�y� jedynie do sprawdzenia poprawno�ci danych od parsera, ale okaza�y
+si� przydatne r�wnie� do ma�ych uproszcze� wyra�e� dokonywanych przy ka�dym kroku.
+Warto�ciowanie tych weryfikator�w jest podobne do r�niczkowania, ka�dy z weryfikator�w dostaje wyra�enie i ma za zadanie
+zwr�ci� jego uproszczon�/zmienion� wersj�. 
+
+Weryfikacja danych od parsera nie jest g��boko rozwini�ta, obecnie polega wy��cznie na sprawdzeniu
+czy podstawa logarytmy jest wyra�eniem sta�ym - bo w takim wypadku program sobie nie radzi. Je�li u�ytkownik
+nie okre�li� podstawy logarytmu to jest okre�lana jako 10.
+
+Wyra�enia uproszaczaj�ce powstawa�y spontanicznie na testach programu, dlatego ich opis znajduje si�
+w kodzie �r�d�owym. Niestety obecne algorytmy nie s� w stanie sobie poradzi� z ``�a�cuszkami'' wyra�e�.
+Np niech $(x + (3+6))$ oznacza wyra�enie b�d�ce operatorem dodawania, z�o�onym z zmiennej i innego operatora dodawania.
+Procesor weryfikuj�cy rozpozna dodawanie liczby do liczby i zamieni $(3+6)$ na 9. Natomiast w przypadku
+ $(3 + (x + 6))$ obecne wyra�enia nie s� w stanie sobie poradzi�. Jednak zagadnienie jest do�c ciekawe
+i pewnie po sesji ``poeksperymentuje'' z tym problemem.
+
+\section{Problemy}
+
+\subsection{Pot�gowanie}
+
+Pot�gowanie okaza�o si� najtrudniejsz� rzecz� do zrobienia, w wyniku moich obserwacji postanowi�em potraktowa� je
+jako operator dwuargumentowy. Problem polega� na tym, jak traktowa� wyra�enia postaci $x^x$; w moim rozumieniu
+za funkcj� pot�guj�ca uwa�am pot�gowanie zmiennej do sta�ej, za wyk�adnicz� pot�gowanie sta�ej do zmiennej. Natomiast
+podnoszenie funkcji do funkcji nie pasuje ani do tego ani do tego. Dlatego postanowi�em, �e parser rozpoznaje czy pot�gowanie
+to f. wyk�adnicza czy pot�gowa, sta�a czy w�a�nie wyra�enie postaci funkcja do funkcji.
+
+Tutaj wystarczy zamieni� takie wyra�enie na r�wnowa�n� mu funkcj� wyk�adnicz� o podstawie liczby $e$. Tzn zastosowa� ,,sztuczk�'' ze
+z�o�eniem funkcji wyk�adniczej i logarytmicznej, np $x^x = e^{\ln x^x}$, a takie wyra�enie mo�na ju� zr�niczkowa� bez problemu
+po uproszczeniu $\ln x^x$ do $x \ln x$.
+
+
+\subsection{U�amki}
+
+Przy projektowaniu programu nie wzi�to pod uwage mo�liwo�ci stosowana u�amk�w jako liczb, dlatego operacje arytmetyczne
+zwi�zane z u�amkami nie s� uproszczanie. Przyk�adowy ``brzydki'' wynik programu:
+
+\[\left( \sqrt{x} \right)'\]
+\[\left( \frac{1}{2} \right)   x^{\left( \frac{1}{2} \right)-1}\]
+
+
+
+\section{U�ycie}
+
+\subsubsection{Opcje programu i wej�cie}
+
+Program, niezgodnie z deklaracj�, nie potrzebuje dodatkowego skryptu generuj�cego dokumenty LaTeX. Zamiast tego
+w opcjach programu (tych dost�pnych w tablicy \emph{Sys.argv}) u�ytkownik mo�e zastosowa� prze�aczniki trybu pracy.
+Domy�lnym trybem jest drukowanie wyra�e� matematycznych nadaj�cych si� do bezpo�redniego wklejenia w dokument \TeX .
+
+Prze�acznik -f w��cza obs�ug� wydruku nag��wka dokumentu \LaTeX przed cytatami wyraze�, oraz zako�czenia dokumentu po nich. Ta opcja
+pozwala na wygenerowanie gotowego do wydruku dokumentu \LaTeX . 
+
+Innym prze��cznikiem jest -c, kt�ry pozwala rozwi�za� problem czytelno�ci mno�enia, z tym prze��cznikiem zawsze
+jest drukowany symbol mno�enia w postaci kropki. 
+
+Dodatkow� opcj� s�u�ac� ku wygodzie u�ytkownika jest prze��cznik -m, kt�ry zmienia spos�b cytowania wyra�e� matematycznych
+na taki, kt�ry nadaje si� do bezpo�redniego wklejenia na stron� www.mathbin.net. Umo�liwia to korzystania z programu na
+kompterach, gdzie system \LaTeX nie jest zainstalowany.
+
+Prze��czniki nie mog� by� �aczone, tzn opcja -cm nie jest prawid�owa.
+
+Program jako wej�cia u�ywa j�zyka TeX, wej�cie ko�czy si� wraz z ko�cem pliku. W systemie UNIX
+mo�na nacisn�c enter i nacisn�c CTRL+D w celu zako�czenia strumienia wej�ciowego podczas pracy programu.
+
+Parser nie rozpoznaje w pe�ni j�zyka TeX, np wyra�enie typu sqrt[u] \{x\} nie jest poprawne, za wyjatkiem
+samego sqrt \{x\}. Nale�y r�wnie� stosowa� \{ \} w celu jawnego grupowania wyra�e�.
+
+\subsubsection{Przyk�adowe wej�cie}
+
+Fragment dokumentu wygenerowane przez program, kt�ry zosta� u�yty w nast�puj�cy spos�b.
+
+\begin{verbatim}
+     [14:42] zubr:/tmp $ ./rozn -f -c > /tmp/test.tex
+     \arctan { x^{x^2} }
+     ^D
+     [14:42] zubr:/tmp $
+\end{verbatim}
+
+\[\left( \arctan{\left( e^{x^{2}  \cdot  \ln{\left( x \right) }} \right) } \right)'\]
+\[\left( \frac{1}{\left( e^{x^{2}  \cdot  \ln{\left( x \right) }} \right)^{2}+1} \right)  \cdot  \left( e^{x^{2}  \cdot  \ln{\left( x \right) }} \right)'\]
+\[\left( \frac{1}{\left( e^{x^{2}  \cdot  \ln{\left( x \right) }} \right)^{2}+1} \right)  \cdot  e^{x^{2}  \cdot  \ln{\left( x \right) }}  \cdot  \left( x^{2}  \cdot  \ln{\left( x \right) } \right)'\]
+\[\left( \frac{1}{\left( e^{x^{2}  \cdot  \ln{\left( x \right) }} \right)^{2}+1} \right)  \cdot  \left( \left( x^{2} \right)'  \cdot  \ln{\left( x \right) }+\left( \ln{\left( x \right) } \right)'  \cdot  x^{2} \right)  \cdot  e^{x^{2}  \cdot  \ln{\left( x \right) }}\]
+\[\left( \frac{1}{\left( e^{x^{2}  \cdot  \ln{\left( x \right) }} \right)^{2}+1} \right)  \cdot  \left( 2  \cdot  x  \cdot  \ln{\left( x \right) }+\left( \frac{1}{x} \right)  \cdot  x^{2} \right)  \cdot  e^{x^{2}  \cdot  \ln{\left( x \right) }}\]
+
+
+inny fragment:
+
+\begin{verbatim}
+     [14:42] zubr:/tmp $ ./rozn -f > /tmp/test.tex
+     x^{0.5}
+     ^D
+     [14:42] zubr:/tmp $
+\end{verbatim}
+
+\[\left( \sqrt{x} \right)'\]
+\[0,5   \left( \frac{1}{\sqrt{x}} \right)\]
+
+
+jeszcze inny:
+
+\begin{verbatim}
+     [14:42] zubr:/tmp $ ./rozn -c -f > /tmp/test.tex
+     c * ( \ln {e} + 0*(5+x) + x^2 )
+     ^D
+     [14:42] zubr:/tmp $
+\end{verbatim}
+
+\[\left( c  \cdot  \left( \ln{\left( e \right) }+x^{2} \right) \right)'\]
+\[c  \cdot  \left( 1+x^{2} \right)'\]
+\[c  \cdot  \left( \left( 1 \right)'+\left( x^{2} \right)' \right)\]
+\[c  \cdot  2  \cdot  x\]
+
+ostatni:
+{
+\footnotesize
+
+\begin{verbatim}
+     [14:42] zubr:/tmp $ ./rozn -c -f > /tmp/test.tex
+     \log_{a} {\frac{x^8 + x^2}{x^3 * (x - 10)}}
+     ^D
+     [14:42] zubr:/tmp $
+\end{verbatim}
+
+\[\left( \log_{a}{\left( \frac{x^{8}+x^{2}}{\left( x-10 \right)  \cdot  x^{3}} \right)} \right)'\]
+\[\left( \frac{1}{\left( \frac{x^{8}+x^{2}}{\left( x-10 \right)  \cdot  x^{3}} \right)  \cdot  \ln{\left( a \right) }} \right)  \cdot  \left( \frac{x^{8}+x^{2}}{\left( x-10 \right)  \cdot  x^{3}} \right)'\]
+\[\left( \frac{1}{\left( \frac{x^{8}+x^{2}}{\left( x-10 \right)  \cdot  x^{3}} \right)  \cdot  \ln{\left( a \right) }} \right)  \cdot  \left( \frac{\left( x^{8}+x^{2} \right)'  \cdot  \left( x-10 \right)  \cdot  x^{3}-\left( x^{8}+x^{2} \right)  \cdot  \left( \left( x-10 \right)  \cdot  x^{3} \right)'}{\left( \left( x-10 \right)  \cdot  x^{3} \right)^{2}} \right)\]
+\[\left( \frac{1}{\left( \frac{x^{8}+x^{2}}{\left( x-10 \right)  \cdot  x^{3}} \right)  \cdot  \ln{\left( a \right) }} \right)  \cdot  \left( \frac{\left( \left( x^{8} \right)'+\left( x^{2} \right)' \right)  \cdot  \left( x-10 \right)  \cdot  x^{3}-\left( x^{8}+x^{2} \right)  \cdot  \left( \left( x-10 \right)'  \cdot  x^{3}+\left( x^{3} \right)'  \cdot  \left( x-10 \right) \right)}{\left( \left( x-10 \right)  \cdot  x^{3} \right)^{2}} \right)\]
+\[\left( \frac{1}{\left( \frac{x^{8}+x^{2}}{\left( x-10 \right)  \cdot  x^{3}} \right)  \cdot  \ln{\left( a \right) }} \right)  \cdot  \left( \frac{\left( 8  \cdot  x^{7}+2  \cdot  x \right)  \cdot  \left( x-10 \right)  \cdot  x^{3}-\left( x^{8}+x^{2} \right)  \cdot  \left( \left( \left( x \right)'+\left( 10 \right)' \right)  \cdot  x^{3}+3  \cdot  x^{2}  \cdot  \left( x-10 \right) \right)}{\left( \left( x-10 \right)  \cdot  x^{3} \right)^{2}} \right)\]
+\[\left( \frac{1}{\left( \frac{x^{8}+x^{2}}{\left( x-10 \right)  \cdot  x^{3}} \right)  \cdot  \ln{\left( a \right) }} \right)  \cdot  \left( \frac{\left( 8  \cdot  x^{7}+2  \cdot  x \right)  \cdot  \left( x-10 \right)  \cdot  x^{3}-\left( x^{8}+x^{2} \right)  \cdot  \left( x^{3}+3  \cdot  x^{2}  \cdot  \left( x-10 \right) \right)}{\left( \left( x-10 \right)  \cdot  x^{3} \right)^{2}} \right)\]
+}
+
+\end{document}

File src/formula.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+(*
+ * Zgodnie z dokumentacja
+ *)
+
+type const = Value of float | Id of char
+;;
+
+type mathexpr =
+        Operator of string * mathexpr * mathexpr
+      | Functor of string * mathexpr * mathexpr
+      | Const of const
+      | Stop of mathexpr
+      | Variable
+      | Empty
+;;
+
+type processor = mathexpr * mathexpr -> mathexpr
+;;
+
+
+let rec is_const e =
+        let recf (w1, w2) = is_const(w1) && is_const(w2)
+        in match e with
+        Const(c) -> true
+      | Functor(id, w1, w2) -> recf(w1, w2)
+      | Operator(id, w1, w2) -> recf(w1, w2)
+      | _ -> false
+;;
+
+let is_const_value =  function
+        Const(Value(c)) -> true
+      | _ -> false
+;;
+
+let rec is_func = function
+        Empty -> false
+      | Variable -> false
+      | e -> if is_const e
+                then false
+                else true
+;;
+
+
+(*
+ * Takie zabezpieczenie pomocnicze, wyobrazmy sobie taka sytuacje:
+ *
+ * mamy policzyc pochodna: abs(x)x^2
+ *
+ * z obliczen symbolicznych jest tworzone wyrazenie: abs'(x)x^2 + (x^2)'abs(x)
+ * Ale programnie radzi sobie z wartoscia bezwzgledna, i w to miejsce "obliczy"
+ * wyrazenie puste, dlatego te funckje pomocnicze do tworzenia operatorow,
+ * sprawdzaja czy przypadkiem jedno z wyrazen nie jest Puste, jesli tak to
+ * calosc jest nieprawidlowa i tez powinna byc pusta.
+ *
+ * Dzieki temu robie tylko
+ * zrob_dodawanie( oblicz wyrazenie1, oblicz wyrazenie2)
+ * nie martwiac sie o to czy oblicz wyr..1 lub obicz wyr..2 bedzie prawidlowe,
+ * czytelnosc kodu zachowana, a "pustaki" beda obsluzone przez wyrazenie
+ * pomocznicze is_correct w zrob_dodawanie.
+ *)
+
+let __is_correct = function
+        (Empty, _) -> false
+     |  (_, Empty) -> false
+     |  _ -> true
+;;
+
+(*
+ * Kolejne wyrazenie pomocnicze
+ *)
+
+let __do_operator id e1 e2 = if __is_correct (e1, e2)
+                                then Operator(id, e1, e2)
+                                else Empty
+;;
+
+let __do_functor id e1 e2 = if __is_correct (e1, e2)
+                                then Functor(id, e1, e2)
+                                else Empty
+;;
+
+let do_mul e1 e2 = __do_operator "*" e1 e2;;
+let do_add e1 e2 = __do_operator "+" e1 e2;;
+let do_sub e1 e2 = __do_operator "-" e1 e2;;
+let do_div e1 e2 = __do_operator "/" e1 e2;;
+let do_pow e1 e2 = __do_operator "Power" e1 e2;;
+let do_const c = Const(Id(c));;
+let do_value v = Const(Value(v));;
+
+let do_f_log p x = __do_functor "Log" p x;;
+
+let do_f_ln e = do_f_log (do_const 'e') e;;
+
+let is_operator = function
+        Operator(_, _, _) -> true
+      | _ -> false
+;;
+
+let get_oper_name = function
+        Operator(n, _, _) -> n
+      | _ -> "#"
+;;
+
+let get_const_value = function
+        Const(Value c) -> c
+      |  _ -> 0.0
+;;
+
+let rec _print = function
+        Operator(n,a,b) -> "(" ^ (_print a) ^  n ^ (_print b) ^ ")"
+      | Functor(n,a,b) ->  n ^ "(" ^ (_print a) ^ ", " ^ (_print b) ^ ")"
+      | Empty -> "#"
+      | Variable -> "x"
+      | Stop(s) -> "[" ^ (_print s) ^ "]'"
+      | Const(c) -> match c with
+                Value(c) -> string_of_float(c)
+              | Id(c) -> String.make 1 c 
+;;
+
+
+

File src/formula.mli

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+type const = Value of float | Id of char
+;;
+
+type mathexpr =
+        Operator of string * mathexpr * mathexpr
+      | Functor of string * mathexpr * mathexpr
+      | Const of const
+      | Stop of mathexpr
+      | Variable
+      | Empty
+;;
+
+type processor = mathexpr * mathexpr -> mathexpr
+;;
+
+
+val is_const: mathexpr -> bool
+val is_const_value: mathexpr -> bool
+
+val is_func: mathexpr -> bool
+val is_operator: mathexpr -> bool
+
+val do_mul: mathexpr -> mathexpr -> mathexpr
+val do_div: mathexpr -> mathexpr -> mathexpr
+val do_add: mathexpr -> mathexpr -> mathexpr
+val do_sub: mathexpr -> mathexpr -> mathexpr
+val do_pow: mathexpr -> mathexpr -> mathexpr
+val do_const: char -> mathexpr
+val do_value: float -> mathexpr
+
+val do_f_log: mathexpr -> mathexpr -> mathexpr
+val do_f_ln: mathexpr -> mathexpr
+
+val get_oper_name: mathexpr -> string
+val get_const_value: mathexpr -> float

File src/lex.ml

View file
  • Ignore whitespace
+# 1 "src/lex.mll"
+ 
+open Formula;;
+open Lexing;;
+open Yacc;;
+
+let from_n s = float (int_of_string s);;
+let from_f s = float_of_string s;;
+
+let norm s =
+        let x = String.lowercase s
+        and l = String.length s
+        in String.capitalize (String.sub x 1 (l-1));;
+
+
+# 17 "src/lex.ml"
+let __ocaml_lex_tables = {
+  Lexing.lex_base = 
+   "\000\000\236\255\237\255\239\255\242\255\243\255\244\255\245\255\
+    \246\255\247\255\248\255\249\255\061\000\250\255\012\000\253\255\
+    \254\255\255\255\022\000\032\000\119\000\192\000\250\000\052\001\
+    \110\001\168\001\226\001\028\002\111\002\169\002\227\002\029\003\
+    \111\003\169\003\227\003\029\004\087\004\145\004\203\004\005\005\
+    \063\005\121\005";
+  Lexing.lex_backtrk = 
+   "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\004\000\255\255\
+    \255\255\255\255\255\255\003\000\017\000\017\000\017\000\017\000\
+    \017\000\017\000\017\000\017\000\017\000\017\000\017\000\017\000\
+    \017\000\017\000\017\000\014\000\017\000\017\000\015\000\017\000\
+    \017\000\016\000";
+  Lexing.lex_default = 
+   "\255\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\255\255\000\000\255\255\000\000\
+    \000\000\000\000\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255";
+  Lexing.lex_trans = 
+   "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\017\000\017\000\000\000\000\000\017\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \013\000\011\000\003\000\006\000\000\000\005\000\000\000\000\000\
+    \014\000\014\000\014\000\014\000\014\000\014\000\014\000\014\000\
+    \014\000\014\000\018\000\000\000\014\000\014\000\014\000\014\000\
+    \014\000\014\000\014\000\014\000\014\000\014\000\019\000\019\000\
+    \019\000\019\000\019\000\019\000\019\000\019\000\019\000\019\000\
+    \019\000\019\000\019\000\019\000\019\000\019\000\019\000\019\000\
+    \019\000\019\000\000\000\008\000\012\000\007\000\004\000\002\000\
+    \000\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\
+    \016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\
+    \016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\
+    \015\000\016\000\016\000\010\000\000\000\009\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\020\000\020\000\
+    \021\000\020\000\020\000\022\000\020\000\020\000\020\000\020\000\
+    \020\000\025\000\020\000\020\000\020\000\020\000\020\000\024\000\
+    \023\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \001\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\020\000\020\000\020\000\039\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\036\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\033\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\029\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\020\000\020\000\020\000\020\000\026\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\020\000\020\000\020\000\020\000\020\000\
+    \027\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \028\000\020\000\020\000\020\000\020\000\020\000\020\000\013\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \030\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\031\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\032\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\034\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\035\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \037\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\020\000\020\000\038\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\040\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\041\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000";
+  Lexing.lex_check = 
+   "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\000\000\000\000\255\255\255\255\000\000\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \000\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \000\000\000\000\000\000\000\000\255\255\000\000\255\255\255\255\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\014\000\255\255\014\000\014\000\014\000\014\000\
+    \014\000\014\000\014\000\014\000\014\000\014\000\018\000\018\000\
+    \018\000\018\000\018\000\018\000\018\000\018\000\018\000\018\000\
+    \019\000\019\000\019\000\019\000\019\000\019\000\019\000\019\000\
+    \019\000\019\000\255\255\000\000\000\000\000\000\000\000\000\000\
+    \255\255\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\
+    \000\000\000\000\000\000\000\000\255\255\000\000\012\000\012\000\
+    \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\
+    \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\
+    \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\
+    \255\255\255\255\255\255\255\255\255\255\255\255\012\000\012\000\
+    \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\
+    \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\
+    \012\000\012\000\012\000\012\000\012\000\012\000\012\000\012\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\255\255\255\255\255\255\255\255\255\255\255\255\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\020\000\020\000\020\000\020\000\020\000\020\000\
+    \020\000\020\000\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \000\000\021\000\021\000\021\000\021\000\021\000\021\000\021\000\
+    \021\000\021\000\021\000\021\000\021\000\021\000\021\000\021\000\
+    \021\000\021\000\021\000\021\000\021\000\021\000\021\000\021\000\
+    \021\000\021\000\021\000\255\255\255\255\255\255\255\255\255\255\
+    \255\255\021\000\021\000\021\000\021\000\021\000\021\000\021\000\
+    \021\000\021\000\021\000\021\000\021\000\021\000\021\000\021\000\
+    \021\000\021\000\021\000\021\000\021\000\021\000\021\000\021\000\
+    \021\000\021\000\021\000\022\000\022\000\022\000\022\000\022\000\
+    \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+    \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+    \022\000\022\000\022\000\022\000\022\000\255\255\255\255\255\255\
+    \255\255\255\255\255\255\022\000\022\000\022\000\022\000\022\000\
+    \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+    \022\000\022\000\022\000\022\000\022\000\022\000\022\000\022\000\
+    \022\000\022\000\022\000\022\000\022\000\023\000\023\000\023\000\
+    \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\
+    \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\
+    \023\000\023\000\023\000\023\000\023\000\023\000\023\000\255\255\
+    \255\255\255\255\255\255\255\255\255\255\023\000\023\000\023\000\
+    \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\
+    \023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\
+    \023\000\023\000\023\000\023\000\023\000\023\000\023\000\024\000\
+    \024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\
+    \024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\
+    \024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\
+    \024\000\255\255\255\255\255\255\255\255\255\255\255\255\024\000\
+    \024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\
+    \024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\
+    \024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\
+    \024\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\
+    \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\
+    \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\
+    \025\000\025\000\025\000\255\255\255\255\255\255\255\255\255\255\
+    \255\255\025\000\025\000\025\000\025\000\025\000\025\000\025\000\
+    \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\
+    \025\000\025\000\025\000\025\000\025\000\025\000\025\000\025\000\
+    \025\000\025\000\025\000\026\000\026\000\026\000\026\000\026\000\
+    \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+    \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+    \026\000\026\000\026\000\026\000\026\000\255\255\255\255\255\255\
+    \255\255\255\255\255\255\026\000\026\000\026\000\026\000\026\000\
+    \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+    \026\000\026\000\026\000\026\000\026\000\026\000\026\000\026\000\
+    \026\000\026\000\026\000\026\000\026\000\027\000\027\000\027\000\
+    \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\
+    \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\
+    \027\000\027\000\027\000\027\000\027\000\027\000\027\000\255\255\
+    \255\255\255\255\255\255\255\255\255\255\027\000\027\000\027\000\
+    \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\
+    \027\000\027\000\027\000\027\000\027\000\027\000\027\000\027\000\
+    \027\000\027\000\027\000\027\000\027\000\027\000\027\000\028\000\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\
+    \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\
+    \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\
+    \028\000\028\000\255\255\255\255\255\255\255\255\255\255\255\255\
+    \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\
+    \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\
+    \028\000\028\000\028\000\028\000\028\000\028\000\028\000\028\000\
+    \028\000\028\000\029\000\029\000\029\000\029\000\029\000\029\000\
+    \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+    \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+    \029\000\029\000\029\000\029\000\255\255\255\255\255\255\255\255\
+    \255\255\255\255\029\000\029\000\029\000\029\000\029\000\029\000\
+    \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+    \029\000\029\000\029\000\029\000\029\000\029\000\029\000\029\000\
+    \029\000\029\000\029\000\029\000\030\000\030\000\030\000\030\000\
+    \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+    \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+    \030\000\030\000\030\000\030\000\030\000\030\000\255\255\255\255\
+    \255\255\255\255\255\255\255\255\030\000\030\000\030\000\030\000\
+    \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+    \030\000\030\000\030\000\030\000\030\000\030\000\030\000\030\000\
+    \030\000\030\000\030\000\030\000\030\000\030\000\031\000\031\000\
+    \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+    \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+    \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+    \255\255\255\255\255\255\255\255\255\255\255\255\031\000\031\000\
+    \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+    \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+    \031\000\031\000\031\000\031\000\031\000\031\000\031\000\031\000\
+    \032\000\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+    \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+    \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+    \032\000\032\000\255\255\255\255\255\255\255\255\255\255\255\255\
+    \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+    \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+    \032\000\032\000\032\000\032\000\032\000\032\000\032\000\032\000\
+    \032\000\032\000\033\000\033\000\033\000\033\000\033\000\033\000\
+    \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+    \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+    \033\000\033\000\033\000\033\000\255\255\255\255\255\255\255\255\
+    \255\255\255\255\033\000\033\000\033\000\033\000\033\000\033\000\
+    \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+    \033\000\033\000\033\000\033\000\033\000\033\000\033\000\033\000\
+    \033\000\033\000\033\000\033\000\034\000\034\000\034\000\034\000\
+    \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+    \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+    \034\000\034\000\034\000\034\000\034\000\034\000\255\255\255\255\
+    \255\255\255\255\255\255\255\255\034\000\034\000\034\000\034\000\
+    \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+    \034\000\034\000\034\000\034\000\034\000\034\000\034\000\034\000\
+    \034\000\034\000\034\000\034\000\034\000\034\000\035\000\035\000\
+    \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+    \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+    \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+    \255\255\255\255\255\255\255\255\255\255\255\255\035\000\035\000\
+    \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+    \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+    \035\000\035\000\035\000\035\000\035\000\035\000\035\000\035\000\
+    \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\
+    \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\
+    \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\
+    \036\000\036\000\255\255\255\255\255\255\255\255\255\255\255\255\
+    \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\
+    \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\
+    \036\000\036\000\036\000\036\000\036\000\036\000\036\000\036\000\
+    \036\000\036\000\037\000\037\000\037\000\037\000\037\000\037\000\
+    \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\
+    \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\
+    \037\000\037\000\037\000\037\000\255\255\255\255\255\255\255\255\
+    \255\255\255\255\037\000\037\000\037\000\037\000\037\000\037\000\
+    \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\
+    \037\000\037\000\037\000\037\000\037\000\037\000\037\000\037\000\
+    \037\000\037\000\037\000\037\000\038\000\038\000\038\000\038\000\
+    \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\
+    \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\
+    \038\000\038\000\038\000\038\000\038\000\038\000\255\255\255\255\
+    \255\255\255\255\255\255\255\255\038\000\038\000\038\000\038\000\
+    \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\
+    \038\000\038\000\038\000\038\000\038\000\038\000\038\000\038\000\
+    \038\000\038\000\038\000\038\000\038\000\038\000\039\000\039\000\
+    \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\
+    \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\
+    \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\
+    \255\255\255\255\255\255\255\255\255\255\255\255\039\000\039\000\
+    \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\
+    \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\
+    \039\000\039\000\039\000\039\000\039\000\039\000\039\000\039\000\
+    \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\
+    \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\
+    \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\
+    \040\000\040\000\255\255\255\255\255\255\255\255\255\255\255\255\
+    \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\
+    \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\
+    \040\000\040\000\040\000\040\000\040\000\040\000\040\000\040\000\
+    \040\000\040\000\041\000\041\000\041\000\041\000\041\000\041\000\
+    \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\
+    \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\
+    \041\000\041\000\041\000\041\000\255\255\255\255\255\255\255\255\
+    \255\255\255\255\041\000\041\000\041\000\041\000\041\000\041\000\
+    \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\
+    \041\000\041\000\041\000\041\000\041\000\041\000\041\000\041\000\
+    \041\000\041\000\041\000\041\000\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\
+    \255\255\255\255";
+  Lexing.lex_base_code = 
+   "";
+  Lexing.lex_backtrk_code = 
+   "";
+  Lexing.lex_default_code = 
+   "";
+  Lexing.lex_trans_code = 
+   "";
+  Lexing.lex_check_code = 
+   "";
+  Lexing.lex_code = 
+   "";
+}
+
+let rec token lexbuf =
+    __ocaml_lex_token_rec lexbuf 0
+and __ocaml_lex_token_rec lexbuf __ocaml_lex_state =
+  match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with
+      | 0 ->
+# 23 "src/lex.mll"
+                                        ( token lexbuf )
+# 479 "src/lex.ml"
+
+  | 1 ->
+let
+# 24 "src/lex.mll"
+               x
+# 485 "src/lex.ml"
+= Lexing.sub_lexeme_char lexbuf lexbuf.Lexing.lex_start_pos in
+# 24 "src/lex.mll"
+                                        ( CONST(x) )
+# 489 "src/lex.ml"
+
+  | 2 ->
+# 25 "src/lex.mll"
+                                        ( VARIABLE )
+# 494 "src/lex.ml"
+
+  | 3 ->
+let
+# 26 "src/lex.mll"
+               x
+# 500 "src/lex.ml"
+= Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in
+# 26 "src/lex.mll"
+                                        ( VALUE(from_f x) )
+# 504 "src/lex.ml"
+
+  | 4 ->
+let
+# 27 "src/lex.mll"
+               x
+# 510 "src/lex.ml"
+= Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in
+# 27 "src/lex.mll"
+                                        ( VALUE(from_n x) )
+# 514 "src/lex.ml"
+
+  | 5 ->
+# 28 "src/lex.mll"
+                                        ( LBRACKET_N )
+# 519 "src/lex.ml"
+
+  | 6 ->
+# 29 "src/lex.mll"
+                                        ( RBRACKET_N )
+# 524 "src/lex.ml"
+
+  | 7 ->
+# 30 "src/lex.mll"
+                                        ( LBRACKET_T )
+# 529 "src/lex.ml"
+
+  | 8 ->
+# 31 "src/lex.mll"
+                                        ( RBRACKET_T )
+# 534 "src/lex.ml"
+
+  | 9 ->
+# 32 "src/lex.mll"
+                                        ( LBRACKET_O )
+# 539 "src/lex.ml"
+
+  | 10 ->
+# 33 "src/lex.mll"
+                                        ( RBRACKET_O )
+# 544 "src/lex.ml"
+
+  | 11 ->
+# 34 "src/lex.mll"
+                                        ( PLUS )
+# 549 "src/lex.ml"
+
+  | 12 ->
+# 35 "src/lex.mll"
+                                        ( MINUS )
+# 554 "src/lex.ml"
+
+  | 13 ->
+# 36 "src/lex.mll"
+                                        ( POWER )
+# 559 "src/lex.ml"
+
+  | 14 ->
+# 37 "src/lex.mll"
+                                        ( SQRT )
+# 564 "src/lex.ml"
+
+  | 15 ->
+# 38 "src/lex.mll"
+                                        ( DIV )
+# 569 "src/lex.ml"
+
+  | 16 ->
+# 39 "src/lex.mll"
+                                        ( MULTIPLY )
+# 574 "src/lex.ml"
+
+  | 17 ->
+let
+# 40 "src/lex.mll"
+               x
+# 580 "src/lex.ml"
+= Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in
+# 40 "src/lex.mll"
+                                        ( FUNCTOR(norm x) )
+# 584 "src/lex.ml"
+
+  | 18 ->
+# 41 "src/lex.mll"
+                                        ( BASE )
+# 589 "src/lex.ml"
+
+  | 19 ->
+# 42 "src/lex.mll"
+                                        ( EOF )
+# 594 "src/lex.ml"
+
+  | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_token_rec lexbuf __ocaml_lex_state
+
+;;
+

File src/lex.mll

View file
  • Ignore whitespace
+{
+open Formula;;
+open Lexing;;
+open Yacc;;
+
+let from_n s = float (int_of_string s);;
+let from_f s = float_of_string s;;
+
+let norm s =
+        let x = String.lowercase s
+        and l = String.length s
+        in String.capitalize (String.sub x 1 (l-1));;
+
+}
+
+let _int = ['0'-'9']+ 
+let _flt = _int ['.'] _int
+let _opr = ['+'] | ['-'] | ['*'] | ['^']
+let _cnt = ['a'-'w'] | ['y'-'z']
+let _fcn = "\\" (['a'-'z']|['A'-'Z'])+
+
+rule token = parse
+        [ ' ' '\t' '\n' '\r' ]          { token lexbuf }
+     | _cnt as x                        { CONST(x) }
+     | ['x']                            { VARIABLE }
+     | _flt as x                        { VALUE(from_f x) }
+     | _int as x                        { VALUE(from_n x) }
+     | "(" | "\\left("                  { LBRACKET_N }
+     | ")" | "\\right)"                 { RBRACKET_N }
+     | "{"                              { LBRACKET_T }
+     | "}"                              { RBRACKET_T }
+     | "["                              { LBRACKET_O }
+     | "]"                              { RBRACKET_O }
+     | "+"                              { PLUS }
+     | "-"                              { MINUS }
+     | "^"                              { POWER }
+     | "\\sqrt"                         { SQRT }
+     | "\\frac"                         { DIV }
+     | "\\cdot" | "*"                   { MULTIPLY }
+     | _fcn as x                        { FUNCTOR(norm x) }
+     | "_"                              { BASE }
+     | eof                              { EOF }
+
+

File src/main.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+
+open Formula;;
+open Symbolcalc;;
+open Printer;;
+
+
+let fulldoc_enter = function
+    false -> ()
+    | true -> begin
+        print_endline Util.latex_enter;
+        end
+;;
+
+let fulldoc_leave = function
+    false -> ()
+    | true -> begin
+        print_endline Util.latex_leave;
+        end
+;;
+
+
+
+let prlist l s e = 
+    let rec pr i = function
+        (x::xs) -> begin
+            print_string s;
+            print_string (print (verify x));
+            print_endline e;
+            pr (i+1) xs;
+            end
+        | _ -> ()
+        in pr 0 l
+;;
+
+
+let doit = fun () (qs,qe) -> 
+    let lexbuf = Lexing.from_channel stdin
+    in let input = simple (Yacc.main Lex.token lexbuf)
+    in prlist (input :: (calc input)) qs qe
+
+;;
+
+let debug_get_input = fun () ->
+        let lexbuf = Lexing.from_channel stdin
+        in (Yacc.main Lex.token lexbuf)
+;;
+
+let mathbin_mode = function
+    true -> ("[EQ]", "[/EQ]" )
+    | false -> ("\\[", "\\]" )
+;;
+
+
+(*
+ * Jedyna imperatywna czesc programu (nie liczac parsera)
+ *)
+
+let cdot_init = function
+    false -> ()
+    | true -> (Printer.mult_symbol) := " \\cdot "
+;;
+
+let main = fun () ->
+    let check_opt opt = Array.fold_left (fun a x -> a || (("-"^opt) = x)) false Sys.argv
+    in let flag_fulldoc = check_opt "f"
+        and flag_cdot = check_opt "c"
+        and flag_mathbin = check_opt "m"
+    in begin
+        cdot_init flag_cdot;
+        fulldoc_enter flag_fulldoc;
+        doit() (mathbin_mode flag_mathbin);
+        fulldoc_leave flag_fulldoc;
+    end
+;;
+
+main ();;

File src/mathtable.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+open Formula;;
+
+let deriv_table_for_operators = [
+    ("*", Table1.d_mul);
+    ("+", Table0.d_add);
+    ("-", Table0.d_sub);
+    ("*", Table0.d_mul);
+    ("/", Table0.d_div);
+];;
+
+
+let deriv_table_for_functors = [
+    ("Log", Table1.d_log); 
+    ("Log", Table0.d_log);
+    ("Exp", Table0.d_exp);
+    ("Power", Table0.d_pow);
+
+    ("Tg", Table0.d_tg);
+    ("Ctg", Table0.d_ctg);
+    ("Sin", Table0.d_sin);
+    ("Cos", Table0.d_cos);
+    ("Arcsin", Table0.d_arcsin);
+    ("Arccos", Table0.d_arccos);
+    ("Arctg", Table0.d_arctg);
+    ("Arcctg", Table0.d_arcctg);
+];;
+
+
+let verif_table_for_operators = [
+
+    ("Power", Vtable0.v_oper_pow);
+    ("+", Vtable0.v_add);
+    ("-", Vtable0.v_sub);
+    ("*", Vtable0.v_mul);
+    ("/", Vtable0.v_div);
+];;
+
+
+let verif_table_for_functors = [
+    (* Obsluga "funkcji skrotowych" *)
+    ("Ln", Vtable0.v_f_ln);
+
+    ("Log", Vtable0.v_log_a_a); 
+
+    ("Power", Vtable0.v_f_pow);
+    ("Log", Vtable0.v_f_log);
+    ("Exp", Vtable0.v_f_exp);
+    ("Sin", Vtable0.v_f_sin);
+    ("Cos", Vtable0.v_f_cos);
+    ("Arcsin", Vtable0.v_f_arcsin);
+    ("Arccos", Vtable0.v_f_arccos);
+    ("Tg", Vtable0.v_f_tg);
+    ("Ctg", Vtable0.v_f_ctg);
+    ("Arctg", Vtable0.v_f_arctg);
+    ("Arcctg", Vtable0.v_f_arcctg);
+];;
+

File src/mathtable.mli

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+open Formula
+
+val deriv_table_for_operators: (string * processor) list
+val deriv_table_for_functors: (string * processor) list
+val verif_table_for_functors: (string * processor) list
+val verif_table_for_operators: (string * processor) list
+

File src/p.ml

View file
  • Ignore whitespace
+open Formula;;
+open Main;;
+open Symbolcalc;;
+open Symbolsimp;;
+
+
+let inp = do_mul Variable (do_add Variable Variable);;

File src/printer.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+open Formula;;
+
+(*
+ * Pomocnicza funkcja, pozwalajaca rozpoznac czy potrzebujemy wstawic nawias.
+ * 
+ * Mamy naprzyklad wyrazenie (w postaci drzewka):
+ *
+ *           +
+ *         /   \
+ *        -    *
+ *       /\   / \
+ *      1 2  +  ^
+ *          /\  /\
+ *         9 10 3 4
+ *
+ * Powinno byc wydrukowane jako
+ *
+ * 1 - 2 + (9+10)*(3^4)
+ *
+ * Nadmiar nawiasow nie jest porzadany.
+ *
+ * Dlatego wprowadzilem pewine "porzadek" wsrod operatorow. Jesli operator
+ * zawiera w sobie operatory, ktore sa ostro mniejsze w porzadku to musi
+ * wydrukowac nawias, w przeciwnym wypadku nawias nie jest potrzebny. Porzadek
+ * jest wedlug "sily wiazania".  Np Dodawanie/Odejmowanie slabiej laczy niz
+ * mnozenie np. Jesli mamy
+ *
+ *             *
+ *            /  \
+ *          +     -
+ *         / \    /\
+ *        a   b  c  d
+ *
+ * To operator mnozenia zawiera w sobie operatory, ktore slabiej lacza, wiec
+ * potrzebuje je opatrzec w nawias = (a+b) * (c-d)
+ *
+ *
+ * Wada tego rozwiazania jest to, ze ulamki zawsze sa brane w nawias, gdybym postawil
+ * "priotytet nawiasowania" dzielenia na rowni z mnozeniem, to w tedy licznik i mianownik
+ * bylby wziety w nawias co jest mniej czytelne.
+ *)
+  
+
+let oper_order id =
+    let set = [
+        (2, "+");
+        (2, "-");
+        (4, "*");
+        (0, "/");
+        (10, "Power");
+    ] in fst (List.find (fun (a,b) -> b = id) set)
+;;
+
+(* W polsce uzywamy przecinka a nie kropki *)
+let polish_string_of_float c =
+    let cc = truncate c
+    in let cu = c -. (floor c) 
+    in let cus = string_of_float(cu)
+    in let sign = if (c < 0.0 && cc = 0) then "-" else ""
+    in sign ^  string_of_int(cc) ^ "," ^ (String.sub cus 2 ((String.length cus)-2))
+;;
+
+
+(* Jedyna imperatywna czesc *)
+let mult_symbol = ref " ";;
+
+(*
+ * Duze wyrazenie, ale chyba udalo mi sie zachowac czytelnosc
+ *
+ * poniewaz wszystko uzywa print rekurencyjnie, nie moglem (nie umialem)
+ * czytelnie rozdzielic pr_oper tak, aby print moglo uzywac pr_oper a pr_oper
+ * z print. Bylo na jednej z list zadanie, ktore w pewnym sensie zawiera
+ * rozwiazanie na ten problem (zadanie z newvar() i reset()) ale nie uwazam
+ * aby to bylo czytelniejsze niz tkaie duze wyrezenie.
+ *
+ * Jest to najbrzydszy fragment kodu, ale nie stanowil sedna projektu
+ * - to proste rekurencyjnie drukowanie, nic odkrywczego, wiec skupialem sie
+ * na tym pliku.
+ *)
+
+
+
+
+let rec print = 
+
+let rec do_brackets s = "\\left( " ^ print s ^ " \\right)" 
+
+(* Drukarka operatorow *)
+and pr_oper id left right = 
+    let need_brackets el =
+        if is_operator el
+            then (oper_order id) > (oper_order (get_oper_name el))
+            else false
+        in let print_elem x = if (need_brackets x) then do_brackets x else print x;
+        in match id with
+            "/" -> "\\frac{" ^ (print_elem left) ^ "}{" ^ (print_elem right) ^ "}"
+          | "*" -> let m = do_value (0.0-.1.0)
+                    in if (left=m)
+                        then "-" ^ (print_elem right)
+                        else if (right=m)
+                            then "-" ^ (print_elem left)
+                            else (print_elem left) ^ " " ^ (!mult_symbol) ^ " " ^ (print_elem right)
+          | "Power" ->
+                let prelem e = if (is_operator e || is_func e)
+                    then do_brackets e
+                    else print e
+                in "{" ^ (prelem left)^ "} ^ { " ^ (prelem right) ^ "}"
+          | _ -> (print_elem left) ^ id ^ (print_elem right)
+
+(* Drukarka funktorow *)
+and pr_func id param arg =
+    let need_brackets e = is_operator e || is_func e
+    and sp = print param
+    and sa = print arg
+    in let pf f a = "\\" ^ (String.lowercase f) ^ "{\\left( " ^ a ^ " \\right) }" 
+    in match id with
+        "Log" -> if param=(do_const 'e')
+            then pf "ln" sa
+            else  "\\log_{" ^ sp ^ "}{\\left( " ^ sa ^ " \\right)}"
+        | "Power" -> let normal = (if (need_brackets arg)
+            then do_brackets arg
+            else sa) ^ "^{"^ sp ^"}"
+        in if (param=(do_value 0.5) || param=(do_div (do_value 1.0) (do_value 2.0)))
+            then "\\sqrt{"^ sa ^ "}"
+            else normal
+        | "Exp" -> (if (need_brackets param)
+            then do_brackets param
+            else sp) ^ "^{" ^ sa ^ "}"
+        | "Tg" -> pf "tan" sa
+        | "Ctg" -> pf "cot" sa
+        | "Arctg" -> pf "arctan" sa
+        | "Arcctg" -> pf "arccot" sa
+        | _ -> pf id sa 
+
+(* Glowne wyrazenie drukarki *)
+    in function
+        Variable -> "x"
+        | Stop(s) -> do_brackets s ^ "'"
+        | Operator(n,l,r) -> pr_oper n l r
+        | Functor(n,l,r) -> pr_func n l r
+        | Empty -> "\\mathbb{EMPTY\\_EXPR}"
+        | Const(c) -> match c with
+            Value(c) -> let cn = truncate c
+            (* zabezpieczenie aby nie bylo wydruku liczny calkowitej z przecinkiem *)
+            in if float(cn) = c
+                then string_of_int(cn)
+                else polish_string_of_float(c)
+        | Id(c) -> String.make 1 c
+;;
+
+

File src/printer.mli

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+open Formula;;
+
+val print: mathexpr -> string
+
+val mult_symbol: string ref

File src/registry.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+open Formula;;
+
+
+
+(*
+ * Funkcja przeszukujace rejestr
+ *
+ * Filtruje liste w poszukowaniu krotek opisujacych nasza funkcje,
+ * a potem tworzy liste z drugich elementow.
+ *)
+
+let __reg_find reglist id = snd (Util.unzip
+    (List.filter (fun (a,b) -> a = id) reglist));;
+
+(*
+ * Wyra?enie znajdujace wszystkie procesory dla danego identyfikatora, a
+ * nastepnie tworzy z nich jeden procesor, kt�ry uruchamia sekwencyjnie
+ * te znalezione, a? znajdzie taki, kt�ry umie poradzi? sobie z wyra?eniem
+ *)
+
+let rec find_proc reglist id = 
+    let rec call_list args = function
+        [] -> Empty
+        | p::ps -> let result = p args
+            in if result=Empty
+                then call_list args ps
+                else result
+        in fun args -> call_list args (__reg_find reglist id)
+;;
+
+

File src/registry.mli

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+open Formula
+
+val find_proc: (string * processor) list -> string -> processor

File src/rozn

  • Ignore whitespace
Binary file added.

File src/symbolcalc.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+open Formula;;
+open Mathtable;;
+open Symbolsimp;;
+
+
+
+
+(*
+ * WERYFIKACJA
+ *)
+
+
+let verify_func (id, p, a) = (Registry.find_proc
+    verif_table_for_functors id) (p, a)
+;;
+
+let verify_oper (id, x1, x2) = (Registry.find_proc
+    verif_table_for_operators id) (x1, x2)
+;;
+
+let rec verify = function
+    Functor(id, p, a) -> verify_func (id, verify p, verify a)
+    | Operator(id, x1, x2) -> verify_oper (id, verify x1, verify x2)
+    | Stop(s) -> Stop(verify s)
+    | e -> e
+;;
+
+(*
+ * UPRASZCZANIE
+ *)
+
+let rec simple e =
+        let rec simple' = function
+         Operator("*", x1, x2) -> simple_mul ((simple x1),(simple x2))
+        | Operator(unknown, x1, x2) -> Operator(unknown, simple x1, simple x2)
+        | Functor(func, x1, x2) -> Functor(func, simple x1, simple x2)
+        | Stop(s) -> Stop(simple s)
+        | e -> e
+        in verify (simple' (verify e))
+;;
+
+
+(*
+ * POCHODNE
+ *)
+
+let func_deriv' (id, a, x) = (Registry.find_proc
+    deriv_table_for_functors id) (a,x);;
+
+let func_deriv (id, a, x) = if is_func x 
+    then do_mul (func_deriv' (id, a, x)) (Stop x)
+    else (func_deriv' (id, a , x))
+;;
+
+
+let oper_deriv (id, w1, w2) = (Registry.find_proc
+    deriv_table_for_operators id) (w1,w2)
+
+(* G��wna funckja (fi w dokumentacji) dokonujaca roznizkowania *)
+
+let rec deriv e = let e = verify e 
+    in if is_const e
+        then (do_value 0.0)
+        else match e with
+            Stop(s) -> Stop(deriv s)
+            | Variable -> do_value(1.0)
+            | Functor(id, w1, w2) -> func_deriv(id, w1, w2)
+            | Operator(id, w1, w2) -> oper_deriv(id, w1, w2)
+            | _ -> Empty
+;;
+
+
+(* Funkcja kontynuujaca rozniczkowanie, psi w dokumentacji *)
+
+let rec step = function
+    Operator(n, a, b) -> Operator(n, step a, step b)
+    | Functor(n, a, b) -> Functor(n, step a, step b)
+    | Stop(s) -> deriv s
+    | e -> e
+;;
+
+
+(* Funckja wytwarzajaca liste przeksztalcen *)
+
+let rec calc e = 
+    let rec aux last = 
+        let next = simple (step last)
+        in if next = last
+            then []
+            else next :: (aux next)
+        in (Stop e) :: aux (Stop e)
+;;
+
+
+

File src/symbolcalc.mli

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+open Formula
+val calc: mathexpr -> mathexpr list
+val verify: mathexpr -> mathexpr
+val step: mathexpr -> mathexpr
+val simple: mathexpr -> mathexpr
+val deriv: mathexpr -> mathexpr
+
+

File src/symbolsimp.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program rozniczkujacy funkcje jednej zmiennej
+ *)
+
+(* =======================================
+ * Ten modul nie jest obj�ty dokumentacj�!
+ * ---------------------------------------
+ *
+ * Dodatkowy modu� s�u��cy do uproszczania
+ * wyra�e�.
+ *
+ * Zmiany dotycz�ce ideii z dokumentacji:
+ * W dokumentacji proceosry weryfikuj�ce s�u�� do uproszczania wyra�e�,
+ * praktycznie nie zmieni�em tej ideii lecz doda�em zasad�,
+ * �e te procesory s�u�� do uproszczania wyra�e� o ma�ym zasi�gu.
+ * To znaczy x+(2+3) ==> x+5, poniewa� 2+3 jest operacj� jednego operatora.
+ * Natomiast 2+(x+3) nie zostanie uproszczone, bo to wymaga�oby zrozumienia
+ * i zbadania struktury danego wyra�enia.
+ *
+ * Doda�em jednak mo�liwo�c uproszczania takich wyra�e� za pomoc� nowego
+ * typu wyra�e�.
+ *
+ * S� one oddzielone od weryfikator�w ze wzgl�du na to, �e zawsze
+ * zwracaj� jakie� wyra�enie, co uniemo�liwia u�ycie kolejnych procesor�w.
+ * (Poniewa� zgodnie z idea dokumentacji procesorami mog� by� drobne
+ * wyspecjalizowane przekszta�cenia, kt�re zwracaj� wyra�enie puste
+ * gdy nie mog� "nic" zrobi� - a te wyra�enia porz�dkuj�ce zamieniaj�c
+ * 2+(x-2) na x+0 wykluczy�yby mo�liwo�c uruchomienia innych weryfikator�w,
+ * kt�re by potrafi�y zamieni� x+0 na x).
+ *
+ * Brak powy�szej zasady spowodowa� nieprawid�owe dzia�anie programu
+ * na czwartkowych �wiczeniach, gdzie program u�ywaj�c mojego
+ * eksperymentalnego algorytmu na uproszczanie mno�e� zatrzymywa�
+ * r�niczkowanie, prawdopodiobnie z powodu ze "dodatkowy" algorytm
+ * zamienia� wyra�enie (2*2*2*x*x*2)' na (16*x*x)', nastepnie procesor
+ * r�niczkuj�cy zamienia� to wyra�enie na 16*(x*x)'. Przy koeljnym
+ * kroku r�niczkowania algorytm "dodatkowy" zamienia� 16*(x*x)'
+ * na 16*(1*x*x)' [jeden wzial sie stad, ze algorytm suzkal wyrazen
+ * stalych, majac 1.0 w swoim akumulatorze]. Teraz poniewaz algorytm
+ * byl traktowany jako weryfikator i zwrocil jakies wyrazenie, to kolejny
+ * weryfikator rozponajacy ze 1*x*x mozna zamienic na x*x nie byl uruchamiany.
+ * Funckja rozniczkujaca znow zamieniala 16*(1*x*x)' na 16*(x*x)', a glowny
+ * mechanizm programu zauwazal ze wynik tego przejscia jest taki sam jak
+ * poprzedniego i zatrzymal mechanizm rozniczkowania. (To moje wyjasnienie
+ * czmeu to nie dzialalo, nie wiem czy idealnie trafilem w przyczyne bledu).
+ *
+ * Teraz wyra�enia badaj�ce struktur� wyra�enia sa oddzielna warstwa
+ * programu, dzieki czemu nie maja wplywu na male i drobne weryfikatory.
+ *
+ *)
+
+
+open Formula;;
+
+(*
+ * Pomocnicza funkcja zamieniajaca cykl powtarzajacych
+ * sie ciag operatorow (rozpoznawanych przez funkcje id)
+ * w drzewku na liste par (identyfikator_operatora, to co bylo "operatowane")
+ *
+ * Tzn
+ *
+ *          *
+ *        /  \
+ *    ln(x)   *
+ *           / \
+ *         2^x ln(x)
+ *
+ *  zamieni na [("*",ln(x)); ("*",2^x); ("*",ln(x))];
+ *
+ *
+ *)
+
+let rec operator_chain test = 
+        let collect name a = 
+                if is_operator a
+                        then (operator_chain test a)
+                        else [(name ,a)]         
+        in function
+                Operator(name, a, b) -> if test name
+                                        then (collect name a) @ (collect name b)
+                                        else [("",Operator(name,a,b))]
+              | _ -> failwith "Blad wewnetrzny! Algorytm uproszczania!!"
+;;
+
+
+
+(*
+ * Pomocnicze wyrazenie do filtorowania listy, jako wynik
+ * zwraca liste rzeczy "operatorwanych".
+ *)
+
+let operator_sublist id l = List.map (fun x -> snd x)
+        (List.filter (fun (i,x) -> i=id) l);;
+
+let rec operator_tree id = function
+      | [] -> Empty
+      | [x] -> x
+      | (x::xs) -> Operator(id, x, operator_tree id xs)
+;;
+
+let oper_sort lst = 
+        let order x y = match (x,y) with (* Ustala porzadek w liscie oper. *)
+                (Functor(a,_,_),Functor(b,_,_)) -> String.compare a b
+      |         (Operator(a,_,_),Operator(b,_,_)) -> String.compare a b
+      |         (Functor(a,_,_),Operator(b,_,_)) -> String.compare a b
+      |         (Operator(a,_,_),Functor(b,_,_)) -> String.compare a b
+      |         (Const(_),Functor(_,_,_)) -> -1
+      |         (Functor(_,_,_),Const(_)) -> 1 
+      |         (Const(_), Operator(_,_,_)) -> -1
+      |         (Operator(_,_,_), Const(_)) -> 1
+      |         (Const(Value(_)), Const(Id(_))) -> -1
+      |         (Const(Id(_)), Const(Value(_))) -> 1
+      |         (Const(_), Variable) -> -1
+      |         (Variable, Const(_)) -> 1
+      |         (Variable, _) -> -1
+      |         (_, Variable) -> 1
+      |         (Stop(_), Stop(_)) -> 0
+      |         (Stop(_), _) -> 1
+      |         (_, Stop(_)) -> -1 
+      |         (_,_) -> 0
+     in List.sort order lst;;
+
+(*
+ * Algorytm uproszczania mnozenia
+ *
+ *
+ * Algorytm ciag mnozenia zamienia na liste, nastepnie lista
+ * jest zamienia na liste par, gdzie pierwszym elementem jest
+ * 'obiekt' z lancuszka a drugim potega, tzn ilosc wystapien.
+ * Np wyrazenie
+ *
+ * x^2 * x^{0.5} zostanie zamienione na 
+ * [ (x,2.0); (x,0.5) ] a to mozna uproscic do x^{2.5}
+ *
+ *)
+
+(* Funckja zamieniajaca n^p na (n,p) oraz n na (n,1.0) *)
+
+let get_power (a,b) = match b with
+        | Functor("Power", Const(Value(p)), x) -> (x,p)
+        | n -> (n, 1.0)
+;;
+
+(* Funkcja sumujaca potegi *)
+
+let rec accmul = function
+        | [] -> []
+        | [(a,p)] -> [(a,p)]
+        | ((a,p)::xs) ->
+               let slst = List.filter (fun (b,_) -> b=a) xs
+               and xlst = List.filter (fun (b,_) -> b<>a) xs
+               in let pp = List.fold_left (fun a (_,x) -> a +. x) p slst
+               in (a,pp) :: (accmul xlst)
+;;
+
+(* Funkcja mnazaca liczby *)
+
+let rec accmul' lst = 
+        let clst = List.filter (fun (b,_) -> is_const_value b) lst
+        and xlst = List.filter (fun (b,_) -> not (is_const_value b)) lst
+        in let const = List.fold_left
+                        (fun p (b,_) -> p*.(get_const_value b))
+                        1.0 clst
+        in (do_value const, 1.0) :: accmul xlst;;
+
+let rec accgen = function
+        | [] -> []
+        | ((a,p)::xs) -> if p=1.0
+                then a :: accgen xs
+                else (Functor("Power", do_value p, a)) :: accgen xs
+;;
+ 
+
+let simple_mul (a,b) = 
+        let lst' = operator_chain (fun n -> n="*") (do_mul a b)
+        in let lst = List.map get_power lst'
+        in operator_tree "*" (oper_sort (accgen (accmul' lst)))
+;;
+
+
+
+
+
+
+(***************)
+

File src/symbolsimp.mli

View file
  • Ignore whitespace
+open Formula;;
+
+
+val simple_mul: processor
+val oper_sort: mathexpr list -> mathexpr list

File src/table0.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+open Formula;;
+
+let d_add (e1,e2) = do_add (Stop e1) (Stop e2);;
+let d_sub (e1,e2) = do_sub (Stop e1) (Stop e2);;
+
+let d_mul (e1,e2) = 
+    let a = do_mul (Stop e1) e2
+    and b = do_mul (Stop e2) e1
+    in do_add a b;;
+
+let d_div (e1,e2) =
+    let l1 = do_mul (Stop e1) e2
+    and l2 = do_mul e1 (Stop e2)
+    and m = Functor ("Power", do_value(2.0), e2)
+    in do_div (do_sub l1 l2) m;;
+
+
+let d_log (e1, e2) = do_div (do_value 1.0)
+    (do_mul e2 (Functor("Log", do_const('e'), e1)))
+;;
+
+
+let d_pow (e1,e2) = do_mul e1
+    (Functor("Power", do_sub e1 (do_value 1.0),e2))
+;;
+
+
+let d_exp (e1,e2) = do_mul (Functor("Exp",e1, e2)) (do_f_ln e1)
+
+
+let d_sin (e1, e2) = Functor("Cos", e1, e2);;
+
+let d_cos (e1, e2) = do_mul (do_value (0.0-.1.0)) (Functor("Sin", e1, e2));;
+
+let d_tg (e1, e2) = do_div (do_value 1.0)
+    (Functor("Power", (do_value 2.0), Functor("Cos",e1,e2)));;
+
+let d_ctg (e1, e2) = do_div (do_value (0.0-.1.0))
+    (Functor("Power", (do_value 2.0), Functor("Sin",e1,e2)));;
+
+let d_arcsin (_, e2) = do_div (do_value 1.0)
+    (Functor("Power", do_value 0.5, (do_sub e2 (do_value 1.0))))
+;;
+
+let d_arccos (_, e2) =
+    do_div (do_value (0.0-.1.0))
+    (Functor("Power", do_value 0.5, 
+        (do_sub e2 (do_value 1.0))))
+;;
+
+let d_arctg (_, x) = do_div (do_value 1.0)
+                                (do_add (Functor("Power", do_value 2.0, x)) (do_value 1.0));;
+
+let d_arcctg (_, x) = do_div (do_value (0.0-.1.0))
+                                (do_add (Functor("Power", do_value 2.0, x)) (do_value 1.0));;

File src/table1.ml

View file
  • Ignore whitespace
+(*
+ * Pawel Wieczorek
+ * Program Rozniczkujacy Funkcje jednej zmiennej
+ *  -- http://trzask.int.pl/~wieczyk/rozn/
+ *
+ *)
+
+open Formula;;
+
+
+(* Wniosek na temat rozniczkowania logarytmu o podstawie liczby e *)
+
+let d_log (e1, e2) = if e1=(do_const 'e')
+                        then do_div (do_value 1.0) e2
+                        else Empty
+;;
+
+