Aliquot sequence classifications: Difference between revisions
Content added Content deleted
(add task to arm assembly raspberry pi) |
(add task to aarch64 assembly raspberry pi) |
||
Line 100: | Line 100: | ||
cyclic back to 1184: [1064, 1336, 1184, 1210] |
cyclic back to 1184: [1064, 1336, 1184, 1210] |
||
non-terminating: [1488, 2480, 3472, 4464, 8432, 9424, 10416, 21328, 22320, 55056, 95728, 96720, 236592, 459792, 881392, 882384, 1474608] |
non-terminating: [1488, 2480, 3472, 4464, 8432, 9424, 10416, 21328, 22320, 55056, 95728, 96720, 236592, 459792, 881392, 882384, 1474608] |
||
</pre> |
|||
=={{header|AArch64 Assembly}}== |
|||
{{works with|as|Raspberry Pi 3B version Buster 64 bits <br> or android 64 bits with application Termux }} |
|||
<lang AArch64 Assembly> |
|||
/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */ |
|||
/* program aliquotSeq64.s */ |
|||
/*******************************************/ |
|||
/* Constantes file */ |
|||
/*******************************************/ |
|||
/* for this file see task include a file in language AArch64 assembly*/ |
|||
.include "../includeConstantesARM64.inc" |
|||
.equ MAXINUM, 10 |
|||
.equ MAXI, 16 |
|||
.equ NBDIVISORS, 1000 |
|||
/*******************************************/ |
|||
/* Initialized data */ |
|||
/*******************************************/ |
|||
.data |
|||
szMessStartPgm: .asciz "Program 64 bits start \n" |
|||
szMessEndPgm: .asciz "Program normal end.\n" |
|||
szMessErrorArea: .asciz "\033[31mError : area divisors too small.\033[0m \n" |
|||
szMessError: .asciz "\033[31m\nError !!!\033[0m \n" |
|||
szMessErrGen: .asciz "\033[31mError end program.\033[0m \n" |
|||
szMessOverflow: .asciz "\033[31mOverflow function isPrime.\033[0m \n" |
|||
szCarriageReturn: .asciz "\n" |
|||
szLibPerf: .asciz "Perfect \n" |
|||
szLibAmic: .asciz "Amicable \n" |
|||
szLibSoc: .asciz "Sociable \n" |
|||
szLibAspi: .asciz "Aspiring \n" |
|||
szLibCycl: .asciz "Cyclic \n" |
|||
szLibTerm: .asciz "Terminating \n" |
|||
szLibNoTerm: .asciz "No terminating\n" |
|||
/* datas message display */ |
|||
szMessResult: .asciz " @ " |
|||
szMessResHead: .asciz "Number @ :" |
|||
.align 4 |
|||
tbNumber: .quad 11,12,28,496,220,1184,12496,1264460,790,909,562,1064,1488 |
|||
.equ NBNUMBER, (. - tbNumber ) / 8 |
|||
/*******************************************/ |
|||
/* UnInitialized data */ |
|||
/*******************************************/ |
|||
.bss |
|||
.align 4 |
|||
sZoneConv: .skip 24 |
|||
tbZoneDecom: .skip 8 * NBDIVISORS // facteur 4 octets |
|||
tbNumberSucc: .skip 8 * MAXI |
|||
/*******************************************/ |
|||
/* code section */ |
|||
/*******************************************/ |
|||
.text |
|||
.global main |
|||
main: // program start |
|||
ldr x0,qAdrszMessStartPgm // display start message |
|||
bl affichageMess |
|||
mov x4,#1 |
|||
1: |
|||
mov x0,x4 // number |
|||
bl aliquotClassif // aliquot classification |
|||
cmp x0,#-1 // error ? |
|||
beq 99f |
|||
add x4,x4,#1 |
|||
cmp x4,#MAXINUM |
|||
ble 1b |
|||
ldr x5,qAdrtbNumber // number array |
|||
mov x4,#0 |
|||
2: |
|||
ldr x0,[x5,x4,lsl #3] // load a number |
|||
bl aliquotClassif // aliquot classification |
|||
cmp x0,#-1 // error ? |
|||
beq 99f |
|||
add x4,x4,#1 // next number |
|||
cmp x4,#NBNUMBER // maxi ? |
|||
blt 2b // no -> loop |
|||
ldr x0,qAdrszMessEndPgm // display end message |
|||
bl affichageMess |
|||
b 100f |
|||
99: // display error message |
|||
ldr x0,qAdrszMessError |
|||
bl affichageMess |
|||
100: // standard end of the program |
|||
mov x0, #0 // return code |
|||
mov x8, #EXIT // request to exit program |
|||
svc 0 // perform system call |
|||
qAdrszMessStartPgm: .quad szMessStartPgm |
|||
qAdrszMessEndPgm: .quad szMessEndPgm |
|||
qAdrszMessError: .quad szMessError |
|||
qAdrszCarriageReturn: .quad szCarriageReturn |
|||
qAdrtbZoneDecom: .quad tbZoneDecom |
|||
qAdrszMessResult: .quad szMessResult |
|||
qAdrsZoneConv: .quad sZoneConv |
|||
qAdrtbNumber: .quad tbNumber |
|||
/******************************************************************/ |
|||
/* function aliquot classification */ |
|||
/******************************************************************/ |
|||
/* x0 contains number */ |
|||
aliquotClassif: |
|||
stp x4,lr,[sp,-16]! // save registres |
|||
stp x5,x6,[sp,-16]! // save registres |
|||
stp x7,x8,[sp,-16]! // save registres |
|||
mov x5,x0 // save number |
|||
ldr x1,qAdrsZoneConv |
|||
bl conversion10 // convert ascii string |
|||
strb wzr,[x1,x0] |
|||
ldr x0,qAdrszMessResHead |
|||
ldr x1,qAdrsZoneConv |
|||
bl strInsertAtCharInc // put in head message |
|||
bl affichageMess // and display |
|||
mov x0,x5 // restaur number |
|||
ldr x7,qAdrtbNumberSucc // number successif array |
|||
mov x4,#0 // counter number successif |
|||
1: |
|||
mov x6,x0 // previous number |
|||
ldr x1,qAdrtbZoneDecom |
|||
bl decompFact // create area of divisors |
|||
cmp x0,#0 // error ? |
|||
blt 99f |
|||
sub x3,x1,x6 // sum |
|||
mov x0,x3 |
|||
ldr x1,qAdrsZoneConv |
|||
bl conversion10 // convert ascii string |
|||
strb wzr,[x1,x0] |
|||
ldr x0,qAdrszMessResult |
|||
ldr x1,qAdrsZoneConv |
|||
bl strInsertAtCharInc // and put in message |
|||
bl affichageMess |
|||
cmp x3,#0 // sum = zero |
|||
bne 11f |
|||
ldr x0,qAdrszLibTerm // terminating |
|||
bl affichageMess |
|||
b 100f |
|||
11: |
|||
cmp x5,x3 // compare number and sum |
|||
bne 4f |
|||
cmp x4,#0 // first loop ? |
|||
bne 2f |
|||
ldr x0,qAdrszLibPerf // perfect |
|||
bl affichageMess |
|||
b 100f |
|||
2: |
|||
cmp x4,#1 // second loop ? |
|||
bne 3f |
|||
ldr x0,qAdrszLibAmic // amicable |
|||
bl affichageMess |
|||
b 100f |
|||
3: // other loop |
|||
ldr x0,qAdrszLibSoc // sociable |
|||
bl affichageMess |
|||
b 100f |
|||
4: |
|||
cmp x6,x3 // compare sum and (sum - 1) |
|||
bne 5f |
|||
ldr x0,qAdrszLibAspi // aspirant |
|||
bl affichageMess |
|||
b 100f |
|||
5: |
|||
cmp x3,#1 // if one ,no search in array |
|||
beq 7f |
|||
mov x2,#0 // search indice |
|||
6: // search number in array |
|||
ldr x9,[x7,x2,lsl #3] |
|||
cmp x9,x3 // equal ? |
|||
beq 8f // yes -> cycling |
|||
add x2,x2,#1 // increment indice |
|||
cmp x2,x4 // end ? |
|||
blt 6b // no -> loop |
|||
7: |
|||
cmp x4,#MAXI |
|||
blt 10f |
|||
ldr x0,qAdrszLibNoTerm // no terminating |
|||
bl affichageMess |
|||
b 100f |
|||
8: // cycling |
|||
ldr x0,qAdrszLibCycl |
|||
bl affichageMess |
|||
b 100f |
|||
10: |
|||
str x3,[x7,x4,lsl #3] // store new sum in array |
|||
add x4,x4,#1 // increment counter |
|||
mov x0,x3 // new number = new sum |
|||
b 1b // and loop |
|||
99: // display error |
|||
ldr x0,qAdrszMessError |
|||
bl affichageMess |
|||
mov x0,-1 |
|||
100: |
|||
ldp x7,x8,[sp],16 // restaur des 2 registres |
|||
ldp x5,x6,[sp],16 // restaur des 2 registres |
|||
ldp x4,lr,[sp],16 // restaur des 2 registres |
|||
ret |
|||
qAdrszMessResHead: .quad szMessResHead |
|||
qAdrszLibPerf: .quad szLibPerf |
|||
qAdrszLibAmic: .quad szLibAmic |
|||
qAdrszLibSoc: .quad szLibSoc |
|||
qAdrszLibCycl: .quad szLibCycl |
|||
qAdrszLibAspi: .quad szLibAspi |
|||
qAdrszLibNoTerm: .quad szLibNoTerm |
|||
qAdrszLibTerm: .quad szLibTerm |
|||
qAdrtbNumberSucc: .quad tbNumberSucc |
|||
/******************************************************************/ |
|||
/* decomposition en facteur */ |
|||
/******************************************************************/ |
|||
/* x0 contient le nombre à decomposer */ |
|||
/* x1 contains factor area address */ |
|||
decompFact: |
|||
stp x3,lr,[sp,-16]! // save registres |
|||
stp x4,x5,[sp,-16]! // save registres |
|||
stp x6,x7,[sp,-16]! // save registres |
|||
stp x8,x9,[sp,-16]! // save registres |
|||
stp x10,x11,[sp,-16]! // save registres |
|||
mov x5,x1 |
|||
mov x1,x0 |
|||
cmp x0,1 |
|||
beq 100f |
|||
mov x8,x0 // save number |
|||
bl isPrime // prime ? |
|||
cmp x0,#1 |
|||
beq 98f // yes is prime |
|||
mov x1,#1 |
|||
str x1,[x5] // first factor |
|||
mov x12,#1 // divisors sum |
|||
mov x4,#1 // indice divisors table |
|||
mov x1,#2 // first divisor |
|||
mov x6,#0 // previous divisor |
|||
mov x7,#0 // number of same divisors |
|||
2: |
|||
mov x0,x8 // dividende |
|||
udiv x2,x0,x1 // x1 divisor x2 quotient x3 remainder |
|||
msub x3,x2,x1,x0 |
|||
cmp x3,#0 |
|||
bne 5f // if remainder <> zero -> no divisor |
|||
mov x8,x2 // else quotient -> new dividende |
|||
cmp x1,x6 // same divisor ? |
|||
beq 4f // yes |
|||
mov x7,x4 // number factors in table |
|||
mov x9,#0 // indice |
|||
21: |
|||
ldr x10,[x5,x9,lsl #3 ] // load one factor |
|||
mul x10,x1,x10 // multiply |
|||
str x10,[x5,x7,lsl #3] // and store in the table |
|||
adds x12,x12,x10 |
|||
bcs 99f |
|||
add x7,x7,#1 // and increment counter |
|||
add x9,x9,#1 |
|||
cmp x9,x4 |
|||
blt 21b |
|||
mov x4,x7 |
|||
mov x6,x1 // new divisor |
|||
b 7f |
|||
4: // same divisor |
|||
sub x9,x4,#1 |
|||
mov x7,x4 |
|||
41: |
|||
ldr x10,[x5,x9,lsl #3 ] |
|||
cmp x10,x1 |
|||
sub x13,x9,1 |
|||
csel x9,x13,x9,ne |
|||
bne 41b |
|||
sub x9,x4,x9 |
|||
42: |
|||
ldr x10,[x5,x9,lsl #3 ] |
|||
mul x10,x1,x10 |
|||
str x10,[x5,x7,lsl #3] // and store in the table |
|||
adds x12,x12,x10 |
|||
bcs 99f |
|||
add x7,x7,#1 // and increment counter |
|||
add x9,x9,#1 |
|||
cmp x9,x4 |
|||
blt 42b |
|||
mov x4,x7 |
|||
b 7f // and loop |
|||
/* not divisor -> increment next divisor */ |
|||
5: |
|||
cmp x1,#2 // if divisor = 2 -> add 1 |
|||
add x13,x1,#1 // add 1 |
|||
add x14,x1,#2 // else add 2 |
|||
csel x1,x13,x14,eq |
|||
b 2b |
|||
/* divisor -> test if new dividende is prime */ |
|||
7: |
|||
mov x3,x1 // save divisor |
|||
cmp x8,#1 // dividende = 1 ? -> end |
|||
beq 10f |
|||
mov x0,x8 // new dividende is prime ? |
|||
mov x1,#0 |
|||
bl isPrime // the new dividende is prime ? |
|||
cmp x0,#1 |
|||
bne 10f // the new dividende is not prime |
|||
cmp x8,x6 // else dividende is same divisor ? |
|||
beq 9f // yes |
|||
mov x7,x4 // number factors in table |
|||
mov x9,#0 // indice |
|||
71: |
|||
ldr x10,[x5,x9,lsl #3 ] // load one factor |
|||
mul x10,x8,x10 // multiply |
|||
str x10,[x5,x7,lsl #3] // and store in the table |
|||
adds x12,x12,x10 |
|||
bcs 99f |
|||
add x7,x7,#1 // and increment counter |
|||
add x9,x9,#1 |
|||
cmp x9,x4 |
|||
blt 71b |
|||
mov x4,x7 |
|||
mov x7,#0 |
|||
b 11f |
|||
9: |
|||
sub x9,x4,#1 |
|||
mov x7,x4 |
|||
91: |
|||
ldr x10,[x5,x9,lsl #3 ] |
|||
cmp x10,x8 |
|||
sub x13,x9,#1 |
|||
csel x9,x13,x9,ne |
|||
bne 91b |
|||
sub x9,x4,x9 |
|||
92: |
|||
ldr x10,[x5,x9,lsl #3 ] |
|||
mul x10,x8,x10 |
|||
str x10,[x5,x7,lsl #3] // and store in the table |
|||
adds x12,x12,x10 |
|||
bcs 99f // overflow |
|||
add x7,x7,#1 // and increment counter |
|||
add x9,x9,#1 |
|||
cmp x9,x4 |
|||
blt 92b |
|||
mov x4,x7 |
|||
b 11f |
|||
10: |
|||
mov x1,x3 // current divisor = new divisor |
|||
cmp x1,x8 // current divisor > new dividende ? |
|||
ble 2b // no -> loop |
|||
/* end decomposition */ |
|||
11: |
|||
mov x0,x4 // return number of table items |
|||
mov x1,x12 // return sum |
|||
mov x3,#0 |
|||
str x3,[x5,x4,lsl #3] // store zéro in last table item |
|||
b 100f |
|||
98: |
|||
add x1,x8,1 |
|||
mov x0,#0 // return code |
|||
b 100f |
|||
99: |
|||
ldr x0,qAdrszMessError |
|||
bl affichageMess |
|||
mov x0,#-1 // error code |
|||
b 100f |
|||
100: |
|||
ldp x10,x11,[sp],16 // restaur des 2 registres |
|||
ldp x8,x9,[sp],16 // restaur des 2 registres |
|||
ldp x6,x7,[sp],16 // restaur des 2 registres |
|||
ldp x4,x5,[sp],16 // restaur des 2 registres |
|||
ldp x3,lr,[sp],16 // restaur des 2 registres |
|||
ret // retour adresse lr x30 |
|||
qAdrszMessErrGen: .quad szMessErrGen |
|||
/***************************************************/ |
|||
/* Verification si un nombre est premier */ |
|||
/***************************************************/ |
|||
/* x0 contient le nombre à verifier */ |
|||
/* x0 retourne 1 si premier 0 sinon */ |
|||
isPrime: |
|||
stp x1,lr,[sp,-16]! // save registres |
|||
stp x2,x3,[sp,-16]! // save registres |
|||
mov x2,x0 |
|||
sub x1,x0,#1 |
|||
cmp x2,0 |
|||
beq 99f // retourne zéro |
|||
cmp x2,2 // pour 1 et 2 retourne 1 |
|||
ble 2f |
|||
mov x0,#2 |
|||
bl moduloPux64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,3 |
|||
beq 2f |
|||
mov x0,#3 |
|||
bl moduloPux64 |
|||
blt 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f |
|||
cmp x2,5 |
|||
beq 2f |
|||
mov x0,#5 |
|||
bl moduloPux64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,7 |
|||
beq 2f |
|||
mov x0,#7 |
|||
bl moduloPux64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,11 |
|||
beq 2f |
|||
mov x0,#11 |
|||
bl moduloPux64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
cmp x2,13 |
|||
beq 2f |
|||
mov x0,#13 |
|||
bl moduloPux64 |
|||
bcs 100f // erreur overflow |
|||
cmp x0,#1 |
|||
bne 99f // Pas premier |
|||
2: |
|||
cmn x0,0 // carry à zero pas d'erreur |
|||
mov x0,1 // premier |
|||
b 100f |
|||
99: |
|||
cmn x0,0 // carry à zero pas d'erreur |
|||
mov x0,#0 // Pas premier |
|||
100: |
|||
ldp x2,x3,[sp],16 // restaur des 2 registres |
|||
ldp x1,lr,[sp],16 // restaur des 2 registres |
|||
ret // retour adresse lr x30 |
|||
/**************************************************************/ |
|||
/********************************************************/ |
|||
/* Calcul modulo de b puissance e modulo m */ |
|||
/* Exemple 4 puissance 13 modulo 497 = 445 */ |
|||
/********************************************************/ |
|||
/* x0 nombre */ |
|||
/* x1 exposant */ |
|||
/* x2 modulo */ |
|||
moduloPux64: |
|||
stp x1,lr,[sp,-16]! // save registres |
|||
stp x3,x4,[sp,-16]! // save registres |
|||
stp x5,x6,[sp,-16]! // save registres |
|||
stp x7,x8,[sp,-16]! // save registres |
|||
stp x9,x10,[sp,-16]! // save registres |
|||
cbz x0,100f |
|||
cbz x1,100f |
|||
mov x8,x0 |
|||
mov x7,x1 |
|||
mov x6,1 // resultat |
|||
udiv x4,x8,x2 |
|||
msub x9,x4,x2,x8 // contient le reste |
|||
1: |
|||
tst x7,1 |
|||
beq 2f |
|||
mul x4,x9,x6 |
|||
umulh x5,x9,x6 |
|||
mov x6,x4 |
|||
mov x0,x6 |
|||
mov x1,x5 |
|||
bl divisionReg128U |
|||
cbnz x1,99f // overflow |
|||
mov x6,x3 |
|||
2: |
|||
mul x8,x9,x9 |
|||
umulh x5,x9,x9 |
|||
mov x0,x8 |
|||
mov x1,x5 |
|||
bl divisionReg128U |
|||
cbnz x1,99f // overflow |
|||
mov x9,x3 |
|||
lsr x7,x7,1 |
|||
cbnz x7,1b |
|||
mov x0,x6 // result |
|||
cmn x0,0 // carry à zero pas d'erreur |
|||
b 100f |
|||
99: |
|||
ldr x0,qAdrszMessOverflow |
|||
bl affichageMess |
|||
cmp x0,0 // carry à un car erreur |
|||
mov x0,-1 // code erreur |
|||
100: |
|||
ldp x9,x10,[sp],16 // restaur des 2 registres |
|||
ldp x7,x8,[sp],16 // restaur des 2 registres |
|||
ldp x5,x6,[sp],16 // restaur des 2 registres |
|||
ldp x3,x4,[sp],16 // restaur des 2 registres |
|||
ldp x1,lr,[sp],16 // restaur des 2 registres |
|||
ret // retour adresse lr x30 |
|||
qAdrszMessOverflow: .quad szMessOverflow |
|||
/***************************************************/ |
|||
/* division d un nombre de 128 bits par un nombre de 64 bits */ |
|||
/***************************************************/ |
|||
/* x0 contient partie basse dividende */ |
|||
/* x1 contient partie haute dividente */ |
|||
/* x2 contient le diviseur */ |
|||
/* x0 retourne partie basse quotient */ |
|||
/* x1 retourne partie haute quotient */ |
|||
/* x3 retourne le reste */ |
|||
divisionReg128U: |
|||
stp x6,lr,[sp,-16]! // save registres |
|||
stp x4,x5,[sp,-16]! // save registres |
|||
mov x5,#0 // raz du reste R |
|||
mov x3,#128 // compteur de boucle |
|||
mov x4,#0 // dernier bit |
|||
1: |
|||
lsl x5,x5,#1 // on decale le reste de 1 |
|||
tst x1,1<<63 // test du bit le plus à gauche |
|||
lsl x1,x1,#1 // on decale la partie haute du quotient de 1 |
|||
beq 2f |
|||
orr x5,x5,#1 // et on le pousse dans le reste R |
|||
2: |
|||
tst x0,1<<63 |
|||
lsl x0,x0,#1 // puis on decale la partie basse |
|||
beq 3f |
|||
orr x1,x1,#1 // et on pousse le bit de gauche dans la partie haute |
|||
3: |
|||
orr x0,x0,x4 // position du dernier bit du quotient |
|||
mov x4,#0 // raz du bit |
|||
cmp x5,x2 |
|||
blt 4f |
|||
sub x5,x5,x2 // on enleve le diviseur du reste |
|||
mov x4,#1 // dernier bit à 1 |
|||
4: |
|||
// et boucle |
|||
subs x3,x3,#1 |
|||
bgt 1b |
|||
lsl x1,x1,#1 // on decale le quotient de 1 |
|||
tst x0,1<<63 |
|||
lsl x0,x0,#1 // puis on decale la partie basse |
|||
beq 5f |
|||
orr x1,x1,#1 |
|||
5: |
|||
orr x0,x0,x4 // position du dernier bit du quotient |
|||
mov x3,x5 |
|||
100: |
|||
ldp x4,x5,[sp],16 // restaur des 2 registres |
|||
ldp x6,lr,[sp],16 // restaur des 2 registres |
|||
ret // retour adresse lr x30 |
|||
/********************************************************/ |
|||
/* File Include fonctions */ |
|||
/********************************************************/ |
|||
/* for this file see task include a file in language AArch64 assembly */ |
|||
.include "../includeARM64.inc" |
|||
</lang> |
|||
<pre> |
|||
Program 64 bits start |
|||
Number 1 : 0 Terminating |
|||
Number 2 : 1 0 Terminating |
|||
Number 3 : 1 0 Terminating |
|||
Number 4 : 3 1 0 Terminating |
|||
Number 5 : 1 0 Terminating |
|||
Number 6 : 6 Perfect |
|||
Number 7 : 1 0 Terminating |
|||
Number 8 : 7 1 0 Terminating |
|||
Number 9 : 4 3 1 0 Terminating |
|||
Number 10 : 8 7 1 0 Terminating |
|||
Number 11 : 1 0 Terminating |
|||
Number 12 : 16 15 9 4 3 1 0 Terminating |
|||
Number 28 : 28 Perfect |
|||
Number 496 : 496 Perfect |
|||
Number 220 : 284 220 Amicable |
|||
Number 1184 : 1210 1184 Amicable |
|||
Number 12496 : 14288 15472 14536 14264 12496 Sociable |
|||
Number 1264460 : 1547860 1727636 1305184 1264460 Sociable |
|||
Number 790 : 650 652 496 496 Aspiring |
|||
Number 909 : 417 143 25 6 6 Aspiring |
|||
Number 562 : 284 220 284 Cyclic |
|||
Number 1064 : 1336 1184 1210 1184 Cyclic |
|||
Number 1488 : 2480 3472 4464 8432 9424 10416 21328 22320 55056 95728 96720 236592 459792 881392 882384 1474608 2461648 No terminating |
|||
Program normal end. |
|||
</pre> |
</pre> |
||