Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
length [] = 0 length x:xs = 1 + length xs
length_helper [] n = n length_helper x:xs n = length_helper xs (n + 1) length xs = length_helper xs 0
length = foldr (const (+1)) 0 :)define i32 @factorial(i32 %n)
{
%ifzero = icmp eq i32 %n, 0
br i1 %ifzero, label %Return1, label %Recursion
Return1:
ret i32 1
Recursion:
%tmp1 = sub i32 %n, 1
%tmp2 = tail call i32 @factorial(i32 %tmp1)
%result = mul i32 %n, %tmp2
ret i32 %result
}
define i32 @factorial(i32 %n) {
%ifzero3 = icmp eq i32 %n, 0
br i1 %ifzero3, label %Return1, label %Recursion
Return1:
%accumulator.tr.lcssa = phi i32 [ 1, %0 ], [ %result, %Recursion ]
ret i32 %accumulator.tr.lcssa
Recursion:
%indvar = phi i32 [ 0, %0 ], [ %indvar.next, %Recursion ]
%accumulator.tr1 = phi i32 [ 1, %0 ], [ %result, %Recursion ]
%n.tr2 = sub i32 %n, %indvar
%result = mul i32 %n.tr2, %accumulator.tr1
%indvar.next = add i32 %indvar, 1
%exitcond = icmp eq i32 %indvar.next, %n
br i1 %exitcond, label %Return1, label %Recursion
}
Речь идёт о компиляторах TopSpeed, которые переводили сначала код в промежуточный формат, которые уже оптимизировался и переводился в машинный код.
$ cat Fibonacci.cОбратите внимание на вполне себе хвостовой вызов функции printf — она как раз находится в другой библиотеке написанной на языке о котором компилятор понятия не имеет (в реальности, конечно, всё равно на C — но этого не требуется).
#include <stdio.h>
int F2(int counter, int a, int b) {
if (counter == 0) return a;
return F2(counter - 1, b, (a + b)%100000);
}
int last5(int number) {
return F2(number, 1, 1);
}
int main(void) {
printf("%d\n",last5(1000));
}
$ gcc -O3 -S Fibonacci.c
$ cat Fibonacci.s
.file «Fibinacci.c»
.text
.p2align 4,,15
.globl F2
.type F2, @function
F2:
.LFB13:
testl %edi, %edi
movl %esi, %r9d
movl %edx, %r10d
je .L3
movl %edi, %r8d
subl $1, %r8d
je .L5
leal (%r10,%r9), %esi
movl $351843721, %edx
movl %esi, %eax
imull %edx
jmp .L26
.p2align 4,,7
.L28:
leal (%r10,%rsi), %edi
movl $351843721, %r11d
movl %edi, %eax
movl %edi, %ecx
imull %r11d
sarl $31, %ecx
sarl $13, %edx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %edi
cmpl $2, %r8d
je .L12
leal (%rdi,%rsi), %esi
movl %esi, %eax
movl %esi, %ecx
imull %r11d
sarl $31, %ecx
sarl $13, %edx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %esi
cmpl $3, %r8d
je .L14
leal (%rsi,%rdi), %edi
movl %edi, %eax
movl %edi, %ecx
imull %r11d
sarl $31, %ecx
sarl $13, %edx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %edi
cmpl $4, %r8d
je .L16
leal (%rdi,%rsi), %esi
movl %esi, %eax
movl %esi, %ecx
imull %r11d
sarl $31, %ecx
sarl $13, %edx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %esi
cmpl $5, %r8d
je .L18
leal (%rsi,%rdi), %edi
movl %edi, %eax
movl %edi, %ecx
imull %r11d
sarl $31, %ecx
sarl $13, %edx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %edi
cmpl $6, %r8d
je .L20
leal (%rdi,%rsi), %esi
movl %esi, %eax
movl %esi, %ecx
imull %r11d
sarl $31, %ecx
sarl $13, %edx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %esi
cmpl $7, %r8d
je .L22
leal (%rsi,%rdi), %edi
movl %edi, %eax
movl %edi, %ecx
movl %edi, %r9d
imull %r11d
sarl $31, %ecx
sarl $13, %edx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %r9d
cmpl $8, %r8d
je .L3
leal (%r9,%rsi), %edi
movl %edi, %eax
movl %edi, %ecx
movl %edi, %r10d
imull %r11d
sarl $31, %ecx
sarl $13, %edx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %r10d
subl $9, %r8d
je .L5
leal (%r10,%r9), %esi
movl %esi, %eax
imull %r11d
.L26:
movl %esi, %ecx
sarl $13, %edx
sarl $31, %ecx
subl %ecx, %edx
imull $100000, %edx, %edx
subl %edx, %esi
cmpl $1, %r8d
jne .L28
.p2align 4,,7
.L10:
movl %esi, %r10d
.L5:
movl %r10d, %r9d
.L3:
movl %r9d, %eax
ret
.L22:
movl %esi, %edi
.L20:
movl %edi, %esi
.L18:
movl %esi, %edi
.L16:
movl %edi, %esi
.L14:
movl %esi, %edi
.L12:
movl %edi, %esi
jmp .L10
.LFE13:
.size F2, .-F2
.section .rodata.str1.1,«aMS»,@progbits,1
.LC0:
.string "%d\n"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB15:
subq $8, %rsp
.LCFI0:
movl $1, %esi
movl $1000, %edi
movl $1, %edx
call F2
movl $.LC0, %edi
movl %eax, %esi
addq $8, %rsp
xorl %eax, %eax
jmp printf
.LFE15:
.size main, .-main
.p2align 4,,15
.globl last5
.type last5, @function
last5:
.LFB14:
testl %edi, %edi
jne .L37
movl $1, %eax
ret
.p2align 4,,7
.L37:
subl $1, %edi
movl $2, %edx
movl $1, %esi
jmp F2
.LFE14:
.size last5, .-last5
.section .eh_frame,«a»,@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string «zR»
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x1
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB13
.long .LFE13-.LFB13
.uleb128 0x0
.align 8
.LEFDE1:
.LSFDE3:
.long .LEFDE3-.LASFDE3
.LASFDE3:
.long .LASFDE3-.Lframe1
.long .LFB15
.long .LFE15-.LFB15
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB15
.byte 0xe
.uleb128 0x10
.align 8
.LEFDE3:
.LSFDE5:
.long .LEFDE5-.LASFDE5
.LASFDE5:
.long .LASFDE5-.Lframe1
.long .LFB14
.long .LFE14-.LFB14
.uleb128 0x0
.align 8
.LEFDE5:
.ident «GCC: (GNU) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)»
.section .note.GNU-stack,"",@progbits
let rec fib_mod10 n = match n with
| 1 -> 1
| 2 -> 2
| _ -> fib_mod10 (n - 1) + fib_mod10 (n - 2)
let rec fib_helper counter a b = if counter = 0
then a
else fib_helper (counter - 1) b ((a + b)%100000)
let fib_mod10_2 n = fib_helper n 1 1
public class FibonacciArrayOptimized2
{
static public int Last5(int number)
{
int a, b, c;
a = 1;
b = 1;
c = 2;
number -= 2;
while (number > 0)
{
a = (b + c) % 100000;
number--;
if (number == 0)
{
return a;
}
b = (a + c) % 100000;
number--;
if (number == 0)
{
return b;
}
c = (a + b) % 100000;
number--;
}
return c;
}
}
* This source code was highlighted with Source Code Highlighter.static public int Last5(int number)
{
int a = 1;
int b = 1;
int c;
while (number > 0)
{
c = b;
b = (a + b) % 100000;
a = c;
number--;
}
return a;
}
* This source code was highlighted with Source Code Highlighter.class FibonacciCalc
{
static private long[,] tempMatrix = new long[2, 2]{{0, 0},
{0, 0}};
// matr1 = matr1 * matr2
static private void matrixMult(long [,] matr1, long [,] matr2)
{
int i, j, k;
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
{
tempMatrix[i,j] = 0;
for (k = 0; k < 2; k++)
tempMatrix[i,j] += matr1[i,k] * matr2[k,j];
}
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
matr1[i,j] = tempMatrix[i,j] % 100000;
}
static public int Last5(long number)
{
long[,] pow2Matrix = new long[2, 2]{{1, 1},
{1, 0}};
long[,] multMatrix = new long[2, 2]{{1, 0},
{0, 1}};
while (number > 0)
{
if (number % 2 == 1)
{ // multMatrix = multMatrix * pow2Matrix
matrixMult(multMatrix, pow2Matrix);
}
{ // pow2Matrix = pow2Matrix * pow2Matrix
matrixMult(pow2Matrix, pow2Matrix);
}
number = number / 2;
}
return (int)multMatrix[0,0];
}
}
}
* This source code was highlighted with Source Code Highlighter.
Оптимизация хвостовой рекурсии в .NET и Nemerle