Path: csiph.com!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Safety of casting from 'long' to 'int' Date: Sat, 09 May 2026 06:35:06 -0700 Organization: A noiseless patient Spider Lines: 157 Message-ID: <86mry8so39.fsf@linuxsc.com> References: <10su8cn$am9i$1@dont-email.me> <10thrud$1v1r3$1@dont-email.me> <10tibhl$ba1$1@reader1.panix.com> <10tie4h$1l93l$1@dont-email.me> <10tiu79$obc$1@reader1.panix.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Date: Sat, 09 May 2026 13:35:10 +0000 (UTC) Injection-Info: dont-email.me; logging-data="3864365"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+3bCcwDDDF/TuT0txw/EP3kqNdXvUEsLM="; posting-host="241722c71660d3e26e4790da0fa3960c" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:aKE0zhKA7MtdF9P/FyPlGNaC+aQ= sha1:4nmP+G/J/0ekaPPBD85Sj1PX2B4= sha256:RDGlZf4zPY3neZkBbyfozU0i8Gbvl1Hr4rpqvYaiFLA= sha1:IZ8dtdhSjx6v93MgNM/vbKX5J98= Xref: csiph.com comp.lang.c:398583 cross@spitfire.i.gajendra.net (Dan Cross) writes: [some non-C, some C] > To get a taste for the flavor of SML, you may find > https://www.cs.cmu.edu/~rwh/isml/book.pdf interesting. > > The Fibonacci example that in this "M" language is: > > |func fib(n)= > | if n<3 then > | 1 > | else > | fib(n-1)+fib(n-2) > | fi > |end > > [sic: as a sequence, the Fibonacci numbers are undefined for > $n<0$, but this is a pedagogical example, so let's ignore that] A comment on that further down... > In SML, this same program could be written as: > > ``` > fun fib(n) = > if n<3 then > 1 > else > fib(n-1) + fib(n-2) > ``` > > Here I'm trying to follow his style. Somewhat more > idiomatically style, would probably be written like: > > ``` > fun fib n = > if n < 3 then 1 > else fib (n - 1) + fib (n - 2) > ``` > > Though typically one would use pattern matching so as to more > closely match the mathemtical definition of the Fibonacci > numbers, expressed as a recurrence relation: > > ``` > fun fib 0 = 1 > | fib 1 = 1 > | fib n = fib (n - 1) + fib (n - 2) > ``` > > (Origin 0, not 1.) fibonacci(0) is 0. There is no other. > But note that so far all of these programs are exponential in > both space and time. A more robust version, mirroring Harper's, > that runs in linear time and space is: > > ``` > exception Range of string > > fun fib n = > let fun fib' 0 = (1, 0) > | fib' 1 = (1, 1) > | fib' n = > let val (a, b) = fib' (n - 1) > in (a + b, a) > end > in if n >= 0 > then #1 (fib' n) > else raise Range "fib: n must be non-negative" > end > ```` Usually the fibonacci function is defined for negative numbers through the same recurrence relation, so fib(n) is defined in terms of fib(n+1) and fib(n+2). Here is (an exponential) fib written in OCaml: let rec fib = function | 0 -> 0 | 1 -> 1 | k when k > 1 -> fib (k-2) + fib (k-1) | k -> fib (k+2) - fib (k+1) Incidentally, fibonacci(-n) = fibonacci(n), except with alternating signs: ..., -8, 5, -3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8, ... > A tail recursive version that runs in linear time and constant > space is: > > ``` > exception Range of string > > fun fib n = > let fun fib' 0 a _ = a > | fib' n a b = fib' (n - 1) (a + b) a > in if n >= 0 > then fib' n 1 0 > else raise Range "fib: n must be non-negative" > end > ``` > > Of course, in C, one might write the last as something like: > > ``` > unsigned int > fib(unsigned int n) > { > unsigned int a = 1, b = 0; > while (n-- > 0) { > unsigned int sum = a + b; > b = a; > a = sum; > } > return a; > } > ``` Here is my current favorite (for C) linear fibonacci function: typedef unsigned long long ULL; ULL sfibonacci( unsigned n ){ ULL a = 0, b = 1; while( n > 1 ) a += b, b += a, n -= 2; return !n ? a : b; } Here is my current favorite fast fibonacci function (which happens to be written in a functional and tail-recursive style): static ULL ff( ULL, ULL, unsigned, unsigned ); static unsigned lone( unsigned ); ULL ffibonacci( unsigned n ){ return ff( 1, 0, lone( n ), n ); } ULL ff( ULL a, ULL b, unsigned m, unsigned n ){ ULL c = a+b; return m & n ? ff( (a+c)*b, b*b+c*c, m>>1, n ) : m ? ff( a*a+b*b, (a+c)*b, m>>1, n ) : /*****/ b; } unsigned lone( unsigned n ){ return n |= n>>1, n |= n>>2, n |= n>>4, n ^ n>>1; } Much faster than the linear version.