Aliquot sequence classifications: Difference between revisions

add task to aarch64 assembly raspberry pi
(add task to arm assembly raspberry pi)
(add task to aarch64 assembly raspberry pi)
Line 100:
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]
</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>