				%FIBONACCI, 25-jan-2014
% Employ pragma declaration.
% Buggy at 93 input, negative number returned.

%fibonacciSa 487>uname -a
%Darwin luke-immess-imac-2.local 13.0.0 Darwin Kernel Version 13.0.0: Thu Sep 19 22:22:27 PDT 2013; root:xnu-2422.1.72~6/RELEASE_X86_64 x86_64

%fibonacciSa 485>gcc --version
%i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5646)
%Copyright (C) 2007 Free Software Foundation, Inc.
%This is free software; see the source for copying conditions.  There is NO
%warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
%
%fibonacciSa 483>

%fibonacciSa 483>mmc -version
%mercury_compile: invalid grade `ion'
%Mercury Compiler, version 13.05, configured for x86_64-apple-darwin12.5.0
%Copyright (C) 1993-2013 The University of Melbourne
%Usage: mmc [<options>] <arguments>
%Use `mmc --help' for more information.
%fibonacciSa 484>

%BUILD
% fibonacciSa 500>./fibonacciSa.bash
% i.e,
% mmc --make --fully-strict -E -v -O 0 --use-subdirs fibonacciSa

% Lets try:
%fibonacciSa 483>mmc  --grade none.gc.stseg --fully-strict -E -v -O 0 --use-subdirs fibonacciSa
% Same problem, fails at 93.

% RUN
% fibonacciSa 482>./fibonacciS
% 3
% fib(3)=2
% 
% a
% Input is not a number
% 2
% fib(2)=1
% 
% Input is not a number
% 32
% fib(32)=2178309
%
% 23-jan-2014
% memo, i.e., memoization is required for this, without it, 500 keeps on running.
%500
% in: 500, fib(500)=2171430676560690477
%% probably a problem with terminal output of integers:
%726
%in: 726, fib(726)=2053579960004884424
%
%727  
%in: 727, fib(727)=2890094407157389165
%
%728
%in: 728, fib(728)=4943674367162273589
%
%729
%in: 729, fib(729)=7833768774319662754
%
%730
%in: 730, fib(730)=-5669300932227615273
%
%800
%in: 800, fib(800)=-1911348809581434107
%3000
%in: 3000, fib(3000)=-4836296387354562400
%4000
%in: 4000, fib(4000)=483944808890094715
% c^d
%хорошо́ EOF, Quit
%fibonacciSa 500>

:- module fibonacciSa. % name of file, for now
:- interface.
:- import_module io.

:- pred main(io, io).
:- mode main(di, uo) is det.

:- implementation.
:- import_module int, list, string.

:- pred main1(io, io).
:- mode main1(di, uo) is det.

:- func fib(int) = int.
:- mode fib(in) = out is det.

				% If pragma on, then fast but makes mistakes, negative numbers.
				% Starts to fail at:
				%93
				%in: 93, fib(93)=-6246583658587674878
				% Too slow at 40.
:- pragma memo(fib/1).		% cache fib(x) return values!
fib(N) = X :- 
	(if N =< 2 then
		X = 1
	else
		X = fib(N-1) + fib(N-2)
	).
	
main(In, Out) :-
	write_string("Fibonacci...\n", In, Out1),
	main1(Out1, Out).
	
main1(In, Out) :-
     read_line_as_string(Result, In, Out0), % blank line, wait for input from console
     (
	 Result = eof,		% c^d
	format("хорошо́ EOF, Quit\n", [], Out0, Out)
	;  

	 Result = error(Error),
	 format("IO error: %s\n", [s(io.error_message(Error))], Out0, Out) % IO error from readLine
	; 
	
	Result = ok(FibStr),
	(if string.to_int(string.strip(FibStr), N)
	then
	format("in: %s, fib(%d)=%d\n\n", [s(string.strip(FibStr)), i(N), i(fib(N))], Out0, Out1)
	 else
	format("Input is not a number\n", [], Out0, Out1)  % e.g.: letter, a
	),
	main1(Out1, Out)  % tail recursive
     ).