summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assembler/gcd-x86-solaris.s142
-rw-r--r--gcd-amd64.S (renamed from assembler/gcd-x86_64-linux.s)84
-rw-r--r--gcd-gmp.c31
-rw-r--r--gcd-x86.S (renamed from assembler/gcd-x86-linux.s)86
-rwxr-xr-xgcd.apl46
-rw-r--r--gcd.bas41
-rw-r--r--gcd.c36
-rw-r--r--gcd.clj2
-rw-r--r--gcd.cob44
-rw-r--r--gcd.cpp89
-rw-r--r--gcd.cs47
-rw-r--r--gcd.d35
-rw-r--r--gcd.erl28
-rw-r--r--gcd.f901
-rw-r--r--gcd.fs3
-rw-r--r--gcd.hs13
-rw-r--r--gcd.java53
-rw-r--r--gcd.lisp33
-rwxr-xr-xgcd.lua4
-rw-r--r--gcd.ml6
-rw-r--r--gcd.pas6
-rw-r--r--gcd.pro14
-rwxr-xr-xgcd.py18
-rwxr-xr-xgcd.rb1
-rw-r--r--gcd.rs32
-rwxr-xr-xgcd.sh4
26 files changed, 522 insertions, 377 deletions
diff --git a/assembler/gcd-x86-solaris.s b/assembler/gcd-x86-solaris.s
deleted file mode 100644
index 50a93f2..0000000
--- a/assembler/gcd-x86-solaris.s
+++ /dev/null
@@ -1,142 +0,0 @@
-# This program is for Solaris 11 on Intel x86 arch (32 bits).
-# Written for GNU Assembler (as) with AT&T syntax
-
-# To make an executable binary:
-# gcc -nostdlib gcd-x86-solaris.s -o gcd-x86-solaris
-# or
-# as gcd-x86-solaris.s -o gcd-x86-solaris.o && \
-# ld gcd-x86-solaris.o -o gcd-x86-solaris
-
-# On 64 bits system:
-# gcc -m32 -nostdlib gcd-x86-solaris.s -o gcd-x86-solaris
-# or
-# as --32 gcd-x86-solaris.s -o gcd-x86-solaris.o && \
-# ld -melf_i386 gcd-x86-solaris.o -o gcd-x86-solaris
-#
-# To run:
-# ./gcd-x86-solaris 11 22 33 121 792
-# (output should be 11)
-
-
-.data
-
-# Buffer for output:
-buffer:
- .space 32 # enough for 32 bits integer
-buf_end:
- .byte 10 # new line
-
-
-.text
-.globl _start
-
-
-# GCD of two numbers.
-# input: eax, ebx - two numbers
-# output: eax - GCD
-# uses: eax, ebx, edx
-gcd2:
- and %ebx, %ebx # is %ebx == 0 ?
- jz gcd2_exit # %ebx == 0, go to exit and return %eax (GCD)
- xor %edx, %edx # set %edx = 0 */
- div %ebx # divide: %edx:%eax / %ebx, actually: %eax / %ebx
- mov %ebx, %eax # drop quotient in %eax and keep previous %ebx in %eax
- mov %edx, %ebx # put remainder in %ebx
- jmp gcd2
-gcd2_exit:
- ret
-
-
-
-# Print an unsigned integer in eax.
-# input: eax - unsigned integer to print
-# uses: eax, ebx, ecx, edx, edi, buffer
-print:
- mov $10, %ecx # set %ecx = 10 (radix)
- mov $buf_end, %edi
-
-next_digit:
- xor %edx, %edx # set %edx = 0
- div %ecx # divide: %edx:%eax / %ecx, actually: %eax / %ecx
- # %edx is a remainder (0-9), it fits into %dl
- add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1'
- dec %edi # put remainders going from the end of the buffer
- mov %dl, (%edi)
- # now eax is a quotient
- and %eax, %eax # is quotient == 0 ?
- jnz next_digit # quotient is not 0, go on
-
- # printing the number:
- mov $4, %eax # syscall `write'
- mov $buf_end, %edx
- sub %edi, %edx # edx is a number of characters to write (buf_end - edi)
- inc %edx # + new line
- push %edx
- push %edi # first character to write
- push $1 # write to stdout
- push $0 # dummy
- int $0x91 # do syscall (print the number)
- add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!)
-
- ret
-
-
-# Convert string into unsigned integer
-# input: esi - pointer to string
-# output: ebx - unsigned integer
-# uses: eax, ebx, ecx, edi, direction flag
-str2uint:
- xor %ecx, %ecx # it will be the string length
- dec %ecx # ecx = -1 != 0 for repne
- xor %eax, %eax # search for 0 (%eax = %al = 0)
- mov %esi, %edi
- cld # Search forward (std - backward)
- repne scasb # search for 0 (in %al), incrementing edi, decrementing ecx
- not %ecx # invert ecx to have the string length
- dec %ecx # minus ending zero
-
- xor %ebx, %ebx
-str2uint_loop:
- lodsb # going forward from esi
- # HINT: assert '0' <= al <= '9'
- lea (%ebx, %ebx, 4), %ebx # ebx = 4*ebx + ebx = 5*ebx ;-)
- lea -48(%eax, %ebx, 2), %ebx # ebx = 2*ebx + %eax - 48
- # ebx is multiplied by 10 each iteration,
- # eax-48 will be multiplied at the next iteration ;-)
- loop str2uint_loop
- ret
-
-
-
-# Entry point for the program
-_start:
-
- # Access command line, see:
- # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html
- # Example: ./gcd-x86-solaris 11 22 33
- pop %ecx # Get the number of command-line options (4)
- pop %esi # Get the pointer to the program name (./gcd-x86-solaris),
- dec %ecx # minus program name
- jz exit # no arguments are given - exiting
-
- xor %eax, %eax
-gcd_loop:
- pop %esi # get next command line argument
- # Well, we used all registers, now we DO NEED stack :-)
- push %ecx # save argument counter
- push %eax # save current GCD
- call str2uint # convert string at esi to integer at ebx
- pop %eax # restore current GCD
- call gcd2 # gcd of eax and ebx (returned by str2uint)
- # now eax is a GCD
- pop %ecx # restore argument counter
- loop gcd_loop
-
- call print # print eax with GCD
-
-exit:
- mov $1, %eax # exit syscall
- push $0 # exit code = 0
- push $0 # dummy
- int $0x91
-
diff --git a/assembler/gcd-x86_64-linux.s b/gcd-amd64.S
index cc85933..16be38f 100644
--- a/assembler/gcd-x86_64-linux.s
+++ b/gcd-amd64.S
@@ -1,18 +1,36 @@
-# This program is for Linux on Intel x86_64 arch (64 bits).
+# This program is for amd64 arch (64 bits) running Linux, Solaris or FreeBSD.
# Written for GNU Assembler (as) with AT&T syntax
-
-# To make an executable binary:
-# gcc -nostdlib gcd-x86_64-linux.s -o gcd-x86_64-linux
+#
+# Synopsis:
+#
+# $ gcc -nostdlib [-D OS=LINUX] gcd-amd64.S -o gcd-amd64-linux
+# or
+# $ cpp [-D OS=LINUX] gcd-amd64.S | as -o gcd-amd64-linux.o \
+# && ld gcd-amd64-linux.o -o gcd-amd64-linux
+#
+#
+# $ gcc -nostdlib -D OS=SOLARIS gcd-amd64.S -o gcd-amd64-solaris
# or
-# as gcd-x86_64-linux.s -o gcd-x86_64-linux.o && \
-# ld gcd-x86_64-linux.o -o gcd-x86_64-linux
+# $ cpp -D OS=SOLARIS gcd-amd64.S | gas -64 -o gcd-amd64-solaris.o \
+# && gld -m elf_x86_64_sol2 gcd-amd64-solaris.o -o gcd-amd64-solaris
+#
+# $ clang -nostdlib -D OS=FREEBSD gcd-amd64.S -o gcd-amd64-freebsd
+#
+
+#define LINUX 1
+#define SOLARIS 2
+#define FREEBSD 3
+
+#ifndef OS
+#define OS LINUX
+#endif
.data
# Buffer for output:
buffer:
- .space 64 # enough for 64 bits integer
+ .space 64 # enough for a 64-bit integer
buf_end:
.byte 10 # new line
@@ -28,7 +46,7 @@ buf_end:
gcd2:
and %rbx, %rbx # is %rbx == 0 ?
jz gcd2_exit # %rbx == 0, go to exit and return %rax (GCD)
- xor %rdx, %rdx # set %rdx = 0 */
+ xor %rdx, %rdx # set %rdx = 0
div %rbx # divide: %rdx:%rax / %rbx, actually: %rax / %rbx
mov %rbx, %rax # drop quotient in %rax and keep prrvious %rbx in %rax
mov %rdx, %rbx # put remainder in %rbx
@@ -43,28 +61,34 @@ gcd2_exit:
# uses: rax, rbx, rcx, rdx, rdi, buffer
print:
mov $10, %rcx # set %rcx = 10 (radix)
- mov $buf_end, %rdi
+ mov $buf_end, %rsi
next_digit:
xor %rdx, %rdx # set %rdx = 0
div %rcx # divide: %rdx:%rax / %rcx, actually: %rax / %rcx
# %rdx is a remainder (0-9), it fits into %dl
add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1'
- dec %rdi # put remainders going from the end of the buffer
- mov %dl, (%rdi)
+ dec %rsi # put remainders going from the end of the buffer
+ mov %dl, (%rsi)
# now rax is a quotient
and %rax, %rax # is quotient == 0 ?
jnz next_digit # quotient is not 0, go on
-
+
# printing the number:
- mov $4, %rax # syscall `write'
- mov $1, %rbx # write to stdout
- mov %rdi, %rcx # first character to write
+#if OS == LINUX
+ mov $1, %rax # syscall `write'
+#elif OS == SOLARIS
+ mov $4, %rax # syscall `write'
+#elif OS == FREEBSD
+ mov $4, %rax # syscall `write'
+#else
+#error bad OS.
+#endif
+ mov $1, %rdi # write to stdout
mov $buf_end, %rdx
- sub %rdi, %rdx # rdx is a number of characters to write (buf_end - rdi)
+ sub %rsi, %rdx # rdx is a number of characters to write (buf_end - rsi)
inc %rdx # + new line
- int $0x80 # do syscall (print the number)
-
+ syscall # do syscall (print the number at rsi)
ret
@@ -98,11 +122,13 @@ str2uint_loop:
# Entry point for the program
_start:
- # Access command line, see:
- # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html
- # Example: ./gcd-x86_64-linux 11 22 33
+ # Access command line.
+ # Example: ./gcd-amd64-linux 11 22 33
+#if OS == FREEBSD
+ mov %rdi, %rsp
+#endif
pop %rcx # Get the number of command-line options (4)
- pop %rsi # Get the pointer to the program name (./gcd-x86_64-linux),
+ pop %rsi # Get the pointer to the program name (./gcd-amd64-linux),
dec %rcx # minus program name
jz exit # no arguments are given - exiting
@@ -121,7 +147,15 @@ gcd_loop:
call print # print rax with GCD
exit:
- mov $1, %rax # exit syscall
- xor %rbx, %rbx # exit code = 0
- int $0x80
+#if OS == LINUX
+ mov $60, %rax # exit syscall
+#elif OS == SOLARIS
+ mov $1, %rax # exit syscall
+#elif OS == FREEBSD
+ mov $1, %rax # exit syscall
+#else
+#error bad OS.
+#endif
+ xor %rdi, %rdi # exit code = 0
+ syscall
diff --git a/gcd-gmp.c b/gcd-gmp.c
index 41213cc..5bedcd2 100644
--- a/gcd-gmp.c
+++ b/gcd-gmp.c
@@ -45,25 +45,22 @@ main (int argc, char *argv[])
if (argc > 1)
{
n = argc - 1;
- a = malloc (sizeof (mpz_t) * n);
- if (NULL != a)
- {
- for (i = 1; i <= n; i++)
- mpz_init_set_str (a[i - 1], argv[i], 10);
+ a = (mpz_t *) malloc (n * sizeof (mpz_t));
+ if (!a)
+ return EXIT_FAILURE;
- mpz_init (g);
- gcdn (g, a, n);
- mpz_out_str (NULL, 10, g);
- printf ("\n");
+ for (i = 1; i <= n; i++)
+ mpz_init_set_str (a[i - 1], argv[i], 10);
- /* No need actually before exit */
- mpz_clear (g);
- for (i = 1; i <= n; i++)
- mpz_clear (a[i - 1]);
- free (a);
- return EXIT_SUCCESS;
- }
- return EXIT_FAILURE;
+ mpz_init (g);
+ gcdn (g, a, n);
+ mpz_out_str (NULL, 10, g);
+ printf ("\n");
+
+ mpz_clear (g);
+ for (i = 1; i <= n; i++)
+ mpz_clear (a[i - 1]);
+ free (a);
}
return EXIT_SUCCESS;
}
diff --git a/assembler/gcd-x86-linux.s b/gcd-x86.S
index aa46fd3..c8d6c79 100644
--- a/assembler/gcd-x86-linux.s
+++ b/gcd-x86.S
@@ -1,28 +1,36 @@
-# This program is for Linux on Intel x86 arch (32 bits).
+# This program is for Intel x86 arch (32 bits) running Linux, Solaris or FreeBSD.
# Written for GNU Assembler (as) with AT&T syntax
-
-# To make an executable binary:
-# gcc -nostdlib gcd-x86-linux.s -o gcd-x86-linux
+#
+# Synopsis:
+#
+# $ gcc -nostdlib -m32 [-D OS=LINUX] gcd-x86.S -o gcd-x86-linux
# or
-# as gcd-x86-linux.s -o gcd-x86-linux.o && \
-# ld gcd-x86-linux.o -o gcd-x86-linux
-
-# On 64 bits system:
-# gcc -m32 -nostdlib gcd-x86-linux.s -o gcd-x86-linux
+# $ cpp [-D OS=LINUX] gcd-x86.S | as -32 -o gcd-x86-linux.o \
+# && ld -m elf_i386 gcd-x86-linux.o -o gcd-x86-linux
+#
+#
+# $ gcc -nostdlib -m32 -D OS=SOLARIS gcd-x86.S -o gcd-x86-solaris
# or
-# as --32 gcd-x86-linux.s -o gcd-x86-linux.o && \
-# ld -melf_i386 gcd-x86-linux.o -o gcd-x86-linux
+# $ cpp -D OS=SOLARIS gcd-x86.S | gas -32 -o gcd-x86-solaris.o \
+# && gld -m elf_i386_sol2 gcd-x86-solaris.o -o gcd-x86-solaris
#
-# To run:
-# ./gcd-x86-linux 11 22 33 121 792
-# (output should be 11)
+#
+# $ clang -nostdlib -m32 -D OS=FREEBSD gcd-x86.S -o gcd-x86-freebsd
+#
+
+#define LINUX 1
+#define SOLARIS 2
+#define FREEBSD 3
+#ifndef OS
+#define OS LINUX
+#endif
.data
# Buffer for output:
buffer:
- .space 32 # enough for 32 bits integer
+ .space 32 # enough for a 32-bit integer
buf_end:
.byte 10 # new line
@@ -38,7 +46,7 @@ buf_end:
gcd2:
and %ebx, %ebx # is %ebx == 0 ?
jz gcd2_exit # %ebx == 0, go to exit and return %eax (GCD)
- xor %edx, %edx # set %edx = 0 */
+ xor %edx, %edx # set %edx = 0
div %ebx # divide: %edx:%eax / %ebx, actually: %eax / %ebx
mov %ebx, %eax # drop quotient in %eax and keep previous %ebx in %eax
mov %edx, %ebx # put remainder in %ebx
@@ -65,16 +73,35 @@ next_digit:
# now eax is a quotient
and %eax, %eax # is quotient == 0 ?
jnz next_digit # quotient is not 0, go on
-
+
# printing the number:
- mov $4, %eax # syscall `write'
- mov $1, %ebx # write to stdout
- mov %edi, %ecx # first character to write
mov $buf_end, %edx
sub %edi, %edx # edx is a number of characters to write (buf_end - edi)
inc %edx # + new line
+#if OS == LINUX
+ mov $4, %eax # syscall `write'
+ mov $1, %ebx # write to stdout
+ mov %edi, %ecx # first character to write
int $0x80 # do syscall (print the number)
-
+#elif OS == SOLARIS
+ mov $4, %eax # syscall `write'
+ push %edx
+ push %edi # first character to write
+ push $1 # write to stdout
+ push $0 # dummy
+ int $0x91 # do syscall (print the number)
+ add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!)
+#elif OS == FREEBSD
+ mov $4, %eax # syscall `write'
+ push %edx
+ push %edi # first character to write
+ push $1 # write to stdout
+ push $0 # dummy
+ int $0x80 # do syscall (print the number)
+ add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!)
+#else
+#error bad OS.
+#endif
ret
@@ -108,8 +135,7 @@ str2uint_loop:
# Entry point for the program
_start:
- # Access command line, see:
- # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html
+ # Access command line.
# Example: ./gcd-x86-linux 11 22 33
pop %ecx # Get the number of command-line options (4)
pop %esi # Get the pointer to the program name (./gcd-x86-linux),
@@ -132,7 +158,21 @@ gcd_loop:
call print # print eax with GCD
exit:
+#if OS == LINUX
mov $1, %eax # exit syscall
xor %ebx, %ebx # exit code = 0
int $0x80
+#elif OS == SOLARIS
+ mov $1, %eax # exit syscall
+ push $0 # exit code = 0
+ push $0 # dummy
+ int $0x91
+#elif OS == FREEBSD
+ mov $1, %eax # exit syscall
+ push $0 # exit code = 0
+ push $0 # dummy
+ int $0x80
+#else
+#error bad OS.
+#endif
diff --git a/gcd.apl b/gcd.apl
new file mode 100755
index 0000000..3c0060d
--- /dev/null
+++ b/gcd.apl
@@ -0,0 +1,46 @@
+#!/usr/bin/apl --script
+⍝
+⍝ Tested with GNU APL 1.8 (2022-10-25)
+⍝
+⍝ Synopsis:
+⍝ $ ./gcd.apl -- 11 22 121
+⍝ or:
+⍝ $ apl --script [-f] gcd.apl -- 11 22 121
+⍝
+⍝ One-liner, where "∨" is APL's built-in GCD:
+⍝ $ apl --eval "∨/⍎¨(↑⍸{'--'≡⍵}¨a)↓a←⎕ARG" -- 11 22 121
+⍝
+
+⍝ Function to get the script arguments,
+⍝ that is everything after '--':
+∇ r ← sargs; a
+ a ← ⎕ARG
+ r ← (↑⍸{'--'≡⍵}¨a)↓a
+∇
+
+⍝ Function to calculate the GCD of two numbers:
+∇ r ← a gcd2 b
+T: →(b=0)/E ⋄ (a b) ← b (b|a) ⋄ →T
+E: r ← a
+∇
+
+⍝ Recursive version:
+⍝ ∇ r ← a gcd2 b
+⍝ r ← a
+⍝ →(b=0)/0
+⍝ r ← b gcd2 b|a
+⍝ ∇
+
+⍝ Function (lambda) to calculate the GCD of several numbers:
+gcdn ← {gcd2/⍵}
+
+∇ main; a
+ a ← sargs ⍝ Get script arguments
+ →(0=≢a)⍴0 ⍝ Exit the function if no arguments
+ ⎕ ← gcdn⍎¨a ⍝ Convert strings to numbers, calculate and print GCD
+∇
+
+main
+
+)OFF
+
diff --git a/gcd.bas b/gcd.bas
new file mode 100644
index 0000000..f63fd23
--- /dev/null
+++ b/gcd.bas
@@ -0,0 +1,41 @@
+' Tested with FreeBASIC 1.10.0
+'
+' Synopsis:
+' $ fbc -x gcd-bas gcd.bas
+' $ ./gcd-bas 11 22 33 121
+'
+
+FUNCTION gcd2 (BYVAL a AS ULONGINT, BYVAL b AS ULONGINT) AS ULONGINT
+ DIM c AS ULONGINT
+ DO WHILE (b > 0)
+ c = b
+ b = a MOD b
+ a = c
+ LOOP
+ RETURN a
+END FUNCTION
+
+
+FUNCTION gcdn (nums() AS ULONGINT) AS ULONGINT
+ DIM gcd AS ULONGINT = nums(LBOUND(nums))
+ FOR i AS INTEGER = LBOUND(nums) + 1 TO UBOUND(nums)
+ gcd = gcd2(gcd, nums(i))
+ NEXT
+ RETURN gcd
+END FUNCTION
+
+
+DIM argc AS INTEGER = 0
+DO WHILE (LEN(COMMAND(argc + 1)) > 0)
+ argc += 1
+LOOP
+
+IF argc = 0 THEN STOP
+
+DIM nums(argc) AS ULONGINT
+FOR i AS INTEGER = 1 TO argc
+ nums(i) = VALULNG(COMMAND(i))
+NEXT
+
+PRINT gcdn(nums())
+
diff --git a/gcd.c b/gcd.c
index 227be89..5fa3840 100644
--- a/gcd.c
+++ b/gcd.c
@@ -1,10 +1,10 @@
#include <stdlib.h>
#include <stdio.h>
-static unsigned long int
-gcd2 (unsigned long int a, unsigned long int b)
+static unsigned long
+gcd2 (unsigned long a, unsigned long b)
{
- unsigned long int c;
+ unsigned long c;
while (b != 0)
{
c = b;
@@ -14,16 +14,14 @@ gcd2 (unsigned long int a, unsigned long int b)
return a;
}
-static unsigned long int
-gcdn (unsigned long int *a, size_t n)
+static unsigned long
+gcdn (const unsigned long *a, size_t n)
{
- unsigned long int r;
+ unsigned long r;
size_t i;
r = a[0];
for (i = 1; i < n; i++)
- {
- r = gcd2 (r, a[i]);
- }
+ r = gcd2 (r, a[i]);
return r;
}
@@ -31,22 +29,20 @@ gcdn (unsigned long int *a, size_t n)
int
main (int argc, char *argv[])
{
- unsigned long int *a;
+ unsigned long *a;
size_t i, n;
if (argc > 1)
{
n = (size_t) (argc - 1);
- a = (unsigned long int *) malloc (sizeof (unsigned long int) * n);
- if (NULL != a)
- {
- for (i = 1; i <= n; i++)
- a[i - 1] = strtoul (argv[i], NULL, 10);
- printf ("%lu\n", gcdn (a, n));
- free (a);
- return EXIT_SUCCESS;
- }
- return EXIT_FAILURE;
+ a = (unsigned long *) malloc (n * sizeof (unsigned long));
+ if (!a)
+ return EXIT_FAILURE;
+
+ for (i = 1; i <= n; i++)
+ a[i - 1] = strtoul (argv[i], NULL, 10);
+ printf ("%lu\n", gcdn (a, n));
+ free (a);
}
return EXIT_SUCCESS;
}
diff --git a/gcd.clj b/gcd.clj
index 7cee3c3..5296997 100644
--- a/gcd.clj
+++ b/gcd.clj
@@ -12,7 +12,7 @@
(defn gcd2 [a b]
(if (zero? b)
a
- (gcd2 b (mod a b))))
+ (recur b (mod a b))))
(defn gcdn [aa] (reduce gcd2 aa))
diff --git a/gcd.cob b/gcd.cob
new file mode 100644
index 0000000..44a60f9
--- /dev/null
+++ b/gcd.cob
@@ -0,0 +1,44 @@
+ * Tested with GNU COBOL 4
+ *
+ * Synopsis:
+ *
+ * $ cobc -x gcd.cob -o gcd-cob
+ * $ ./gcd-cob 11 22 33 121
+ *
+ IDENTIFICATION DIVISION.
+ PROGRAM-ID. GCD.
+ DATA DIVISION.
+ WORKING-STORAGE SECTION.
+ 01 WS-COUNT PIC 9(20).
+ 01 WS-GCD PIC 9(20).
+ 01 WS-NUM PIC 9(20).
+ 01 WS-OUT PIC Z(20).
+ PROCEDURE DIVISION.
+ ACCEPT WS-COUNT FROM ARGUMENT-NUMBER.
+ IF WS-COUNT = 0 STOP RUN.
+ ACCEPT WS-GCD FROM ARGUMENT-VALUE.
+ PERFORM WITH TEST BEFORE UNTIL WS-COUNT = 1
+ ACCEPT WS-NUM FROM ARGUMENT-VALUE
+ CALL 'GCD2' USING WS-GCD, WS-NUM
+ SUBTRACT 1 FROM WS-COUNT
+ END-PERFORM.
+ MOVE WS-GCD TO WS-OUT.
+ DISPLAY FUNCTION TRIM (WS-OUT LEADING).
+ END PROGRAM GCD.
+
+ IDENTIFICATION DIVISION.
+ PROGRAM-ID. GCD2.
+ DATA DIVISION.
+ WORKING-STORAGE SECTION.
+ 01 WS-C PIC 9(20).
+ LINKAGE SECTION.
+ 01 L-A PIC 9(20).
+ 01 L-B PIC 9(20).
+ PROCEDURE DIVISION USING L-A, L-B.
+ PERFORM WITH TEST BEFORE UNTIL L-B = 0
+ MOVE L-B TO WS-C
+ DIVIDE WS-C INTO L-A GIVING L-A REMAINDER L-B
+ MOVE WS-C TO L-A
+ END-PERFORM.
+ END PROGRAM GCD2.
+
diff --git a/gcd.cpp b/gcd.cpp
index 659c77a..e1d363a 100644
--- a/gcd.cpp
+++ b/gcd.cpp
@@ -7,65 +7,70 @@
*
*
* To use GNU Multiple Precision Arithmetic Library:
- *
- * # g++ -o gcd-cpp-gmp -DGMP -lgmpxx -lgmp gcd.cpp
+ *
+ * # g++ -DGMP gcd.cpp -lgmpxx -lgmp -o gcd-cpp-gmp
* # ./gcd-cpp-gmp 1234567890987654321 987654321234567
* # 63
*
*/
-
#include <cstdlib>
#include <iostream>
-#include <vector>
#include <sstream>
-
-using namespace std;
+#include <vector>
+#if __cplusplus >= 201703L
+#include <execution>
+#include <numeric>
+#endif
#ifdef GMP
- #include <gmpxx.h>
- typedef mpz_class Number;
+#include <gmpxx.h>
+typedef mpz_class Number;
#else
- typedef unsigned int Number;
-#endif // GMP
+typedef unsigned long Number;
+#endif
-typedef vector<Number> Numbers;
+using std::vector;
-Number gcd(Number a, Number b)
-{
- Number c;
- while (b != 0) {
- c = b;
- b = a % b;
- a = c;
- }
- return a;
+template <class N> N gcd2(N a, N b) {
+ while (b != 0) {
+ N c = b;
+ b = a % b;
+ a = c;
+ }
+ return a;
}
-Number gcd(const Numbers & ns)
-{
- Number r = 0;
- for(Numbers::const_iterator n = ns.begin(); n != ns.end(); ++n)
- r = gcd(*n, r);
- return r;
+#if __cplusplus >= 201703L
+template <class N> class GCD {
+public:
+ N operator()(N a, N b) const { return gcd2(a, b); };
+};
+
+template <class N> N gcd(const vector<N> &ns) {
+ GCD<N> GCD;
+ return reduce(std::execution::par, begin(ns), end(ns), N(0), GCD);
}
+#else
-int main (int argc, char *argv[])
-{
- if (argc > 1) {
- Numbers ns(argc - 1);
- for(int n = 1; n < argc; ++n) {
- stringstream str;
- str << argv[n];
- str >> ns[n-1];
- /* NOTE:
- * For GMP we can just assign: ns[n-1] = argv[n],
- * and sstream is not needed.
- */
- }
- cout << gcd(ns) << endl;
- }
- return EXIT_SUCCESS;
+template <class N> N gcd(const vector<N> &ns) {
+ N r = 0;
+ for (typename vector<N>::const_iterator n = ns.begin(); n != ns.end(); ++n)
+ r = gcd2(*n, r);
+ return r;
}
+#endif
+int main(int argc, char *argv[]) {
+ if (argc > 1) {
+ vector<Number> ns(argc - 1);
+ for (int n = 1; n < argc; ++n) {
+ std::stringstream str;
+ str << argv[n];
+ str >> ns[n - 1];
+ }
+ std::cout << gcd(ns) << std::endl;
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/gcd.cs b/gcd.cs
index 0825cea..325e27a 100644
--- a/gcd.cs
+++ b/gcd.cs
@@ -1,32 +1,27 @@
using System;
+using System.Linq;
-namespace GCD {
- class Program {
- static uint gcd2(uint a, uint b) {
- uint c;
- while (b != 0) {
- c = b;
- b = a % b;
- a = c;
- }
- return a;
- }
+class Program {
+ static ulong gcd2(ulong a, ulong b) {
+ ulong c;
+ while (b != 0) {
+ c = b;
+ b = a % b;
+ a = c;
+ }
+ return a;
+ }
- static uint gcdn(uint [] n) {
- uint r = n[0];
- for (int i = 1; i < n.Length; i++)
- r = gcd2(r, n[i]);
- return r;
- }
+ static ulong gcdn(ulong[] nums) {
+ return nums.Aggregate(0UL, (gcd, n) => gcd2(gcd, n));
+ }
- static void Main(string [] argv) {
- uint [] a = Array.ConvertAll<string, uint>(argv,
- new Converter<string, uint>
- (delegate(string s) {return uint.Parse(s);})
- );
+ static void Main(string[] argv) {
+ ulong[] nums = Array.ConvertAll<string, ulong>(
+ argv, new Converter<string, ulong>(
+ delegate(string s) { return ulong.Parse(s); }));
- Console.WriteLine("{0}", gcdn(a));
- }
- }
+ if (nums.Length > 0)
+ Console.WriteLine("{0}", gcdn(nums));
+ }
}
-
diff --git a/gcd.d b/gcd.d
new file mode 100644
index 0000000..b9599e4
--- /dev/null
+++ b/gcd.d
@@ -0,0 +1,35 @@
+// D: https://dlang.org
+//
+// Synopsis:
+//
+// GNU D Compiler (tested GCC 12):
+// $ gdc gcd.d -o gcd-d
+// $ ./gcd-d 11 22 33 121
+//
+// LLVM D Compiler (tested LDC2 1.24.0):
+// $ ldc2 --run gcd 11 22 33 121
+// or
+// $ ldc2 --of=gcd-d gcd.d
+// $ ./gcd-d 11 22 33 121
+//
+
+import std.algorithm: map, reduce;
+import std.conv: to;
+import std.stdio: writeln;
+
+ulong gcd2(ulong a, ulong b) {
+ ulong c;
+ while (b > 0) {
+ c = b;
+ b = a % b;
+ a = c;
+ }
+ return c;
+}
+
+void main(string[] args) {
+ if (args.length > 1) {
+ auto gcd = args[1..$].map!(to!ulong).reduce!gcd2();
+ writeln(gcd);
+ }
+}
diff --git a/gcd.erl b/gcd.erl
new file mode 100644
index 0000000..484bd9e
--- /dev/null
+++ b/gcd.erl
@@ -0,0 +1,28 @@
+% Synopsis:
+%
+% $ escript gcd.erl 11 22 33 121
+%
+% or
+%
+% $ erl -compile gcd / erlc gcd.erl
+% $ erl -noshell -run gcd main 11 22 33 121
+%
+
+-module(gcd).
+-export([main/1, main/0]).
+-mode(compile).
+
+gcd2(A, 0) -> A;
+gcd2(A, B) -> gcd2(B, A rem B).
+
+gcdn(Nums) ->
+ lists:foldl(fun gcd2/2, 0, Nums).
+
+main() -> init:stop().
+
+main([]) -> init:stop();
+main(Args) ->
+ Nums = lists:map(fun erlang:list_to_integer/1, Args),
+ io:format("~w\n", [gcdn(Nums)]),
+ init:stop().
+
diff --git a/gcd.f90 b/gcd.f90
index c17c61c..d95d3d3 100644
--- a/gcd.f90
+++ b/gcd.f90
@@ -12,6 +12,7 @@ program GCD
character(len=20) :: tmpstr
n = command_argument_count()
+ if (n == 0) stop
allocate (ns(n))
diff --git a/gcd.fs b/gcd.fs
index 1baeda0..c66f291 100644
--- a/gcd.fs
+++ b/gcd.fs
@@ -30,7 +30,8 @@
r> 1 + >r
repeat
2drop
- r> gcdn . cr
+ r>
+ dup 0 <> if gcdn . cr else drop endif
;
main bye
diff --git a/gcd.hs b/gcd.hs
index b044c85..e868a1b 100644
--- a/gcd.hs
+++ b/gcd.hs
@@ -14,17 +14,16 @@ or:
-}
import System.Environment (getArgs)
-gcd2 :: Integer -> Integer -> Integer
+gcd2 :: Integral a => a -> a -> a
gcd2 a 0 = a
gcd2 a b = gcd2 b (a `rem` b)
-gcdn :: [Integer] -> Integer
+gcdn :: Integral a => [a] -> a
gcdn = foldl1 gcd2
-str2int :: String -> Integer
-str2int = read
+out :: [String] -> IO ()
+out [] = return ()
+out a = print (gcdn (map read a) :: Integer)
main :: IO ()
-main = do
- a <- getArgs
- print $ gcdn (map str2int a)
+main = getArgs >>= out
diff --git a/gcd.java b/gcd.java
index 82722a1..8770beb 100644
--- a/gcd.java
+++ b/gcd.java
@@ -1,41 +1,38 @@
/*
* SYNOPSIS:
*
- * # gcj -o gcd --main=gcd gcd.java
- * # ./gcd 11 22 33 44 121
- *
* # javac gcd.java
* # java gcd 11 22 33
*
*/
-public class gcd
-{
- public static int gcd2(int a, int b) {
- int c;
- while (b != 0) {
- c = b;
- b = a % b;
- a = c;
- }
- return a;
+public class gcd {
+ public static long gcd2(long a, long b) {
+ long c;
+ while (b != 0) {
+ c = b;
+ b = a % b;
+ a = c;
}
+ return a;
+ }
- public static int gcdn(int [] a) {
- int r = a[0];
- for (int i = 1; i < a.length; i++)
- r = gcd2(r, a[i]);
- return r;
- }
+ public static long gcdn(long[] a) {
+ long r = a[0];
+ for (int i = 1; i < a.length; i++)
+ r = gcd2(r, a[i]);
+ return r;
+ }
+
+ public static void main(String[] argv) {
+ if (argv.length == 0)
+ return;
- public static void main(String [] argv) {
- if (argv.length == 0)
- return;
- int [] n = new int [argv.length];
- for (int i = 0; i < argv.length; i++) {
- n[i] = Integer.parseInt(argv[i]);
- }
- System.out.println(gcdn(n));
+ long[] n = new long[argv.length];
+ for (int i = 0; i < argv.length; i++) {
+ n[i] = Long.parseLong(argv[i]);
}
-}
+ System.out.println(gcdn(n));
+ }
+}
diff --git a/gcd.lisp b/gcd.lisp
index 4bf5840..8899491 100644
--- a/gcd.lisp
+++ b/gcd.lisp
@@ -1,29 +1,30 @@
; SYNOPSIS:
; # clisp gcd.lisp 11 22 33 121
+; # ecl --shell gcd.lisp 121 22 33
+; # gcl -f gcd.lisp 121 22 33
; # sbcl --script gcd.lisp 121 22 33
-;
(defun gcd2 (a b)
- (if (= b 0)
- a
- (gcd2 b (mod a b))))
+ (loop while (/= b 0) do
+ (psetq a b b (mod a b))
+ finally (return a)))
-(defun gcdn (&rest numbers)
- (reduce #'gcd2 (rest numbers)
- :initial-value (first numbers)))
+(defun gcdn (n &rest ns)
+ (reduce #'gcd2 ns :initial-value n))
-; Command line access is different on different Lisps
(defun program-args ()
(or
- #+SBCL (rest *posix-argv*)
#+CLISP *args*
- ;#+ECL (ext:command-args)
- ;#+CMU extensions:*command-line-words*
- ;#+LISPWORKS system:*line-arguments-list*
+ #+ECL (cdr ext:*unprocessed-ecl-command-args*)
+ #+GCL (cdr si::*command-args*)
+ #+SBCL (cdr *posix-argv*)
nil))
-(write (apply #'gcdn
- (map 'list #'parse-integer (program-args))
- ))
-(fresh-line)
+(defun numbers ()
+ (mapcar #'parse-integer (program-args)))
+
+(let ((ns (numbers)))
+ (when ns
+ (write (apply #'gcdn ns))
+ (fresh-line)))
diff --git a/gcd.lua b/gcd.lua
index 43cfad9..fe7c893 100755
--- a/gcd.lua
+++ b/gcd.lua
@@ -21,5 +21,7 @@ function gcdn(ns)
return r
end
-print(gcdn(arg))
+if #arg ~= 0 then
+ print(gcdn(arg))
+end
diff --git a/gcd.ml b/gcd.ml
index 85d64d5..38b44b1 100644
--- a/gcd.ml
+++ b/gcd.ml
@@ -27,7 +27,9 @@ let rec gcd a b =
let gcdn = List.fold_left gcd 0 ;;
let args = List.tl (Array.to_list Sys.argv) ;;
-let nums = List.map int_of_string args ;;
-Printf.printf "%d\n" (gcdn nums) ;;
+if args <> [] then begin
+ let nums = List.map int_of_string args
+ in Printf.printf "%d\n" (gcdn nums)
+end ;;
diff --git a/gcd.pas b/gcd.pas
index 4253807..2461ee8 100644
--- a/gcd.pas
+++ b/gcd.pas
@@ -1,6 +1,6 @@
{
FreePascal: https://www.freepascal.org/
-Tested with FreePascal 2.4.0, 3.0.0
+Tested with FreePascal 3.2
Usage:
@@ -39,8 +39,12 @@ Var
n: array Of integer;
i: integer;
Begin
+ If ParamCount = 0 then exit;
+
SetLength(n, ParamCount);
+
For i := 1 To ParamCount Do
n[i-1] := StrToInt(ParamStr(i));
+
Writeln(gcdn(n))
End.
diff --git a/gcd.pro b/gcd.pro
index bbc460a..793d307 100644
--- a/gcd.pro
+++ b/gcd.pro
@@ -2,12 +2,10 @@
%
% Tested with GNU Prolog 1.3.1
%
-% # gplc --no-top-level gcd.pro
-% # ./gcd 22 33 44 121
+% # gplc --no-top-level -o gcd-pro gcd.pro
+% # ./gcd-pro 22 33 44 121
-% 1st number, 2nd number, GCD
-
% It is true that GCD of A and 0 is A
% (The fact is GCD of A and 0 is A)
gcd2(A, 0, A).
@@ -20,14 +18,18 @@ gcdn(A, [], A).
gcdn(A, [B|Bs], G) :- gcd2(A, B, N), gcdn(N, Bs, G).
gcdn([A|As], G) :- gcdn(A, As, G).
-:- initialization(main).
-
str2int([], []).
str2int([S|St], [N|Nt]) :- number_atom(N, S), str2int(St, Nt).
+not_empty([]) :- halt.
+not_empty(_).
+
main :-
argument_list(Args),
+ not_empty(Args),
str2int(Args, Numbers),
gcdn(Numbers, G),
write(G), nl.
+:- initialization(main).
+
diff --git a/gcd.py b/gcd.py
index d6774a0..df3baf6 100755
--- a/gcd.py
+++ b/gcd.py
@@ -3,16 +3,16 @@
import sys
import functools
+
def gcd2(a, b):
- if b == 0:
- return a
- else:
- return gcd2(b, a % b)
+ while b != 0:
+ a, b = b, a % b
+ return a
+
-def gcdn(ns):
- return functools.reduce(gcd2, ns)
+def gcdn(nums):
+ return functools.reduce(gcd2, nums)
-ints = map(int, sys.argv[1:])
-gcd = gcdn(ints)
-print(gcd)
+if len(sys.argv) > 1:
+ print(gcdn(map(int, sys.argv[1:])))
diff --git a/gcd.rb b/gcd.rb
index 0eefe8a..1fd7d9f 100755
--- a/gcd.rb
+++ b/gcd.rb
@@ -8,7 +8,6 @@ def gcd2 a, b
end
end
-# http://railspikes.com/2008/8/11/understanding-map-and-reduce
def gcdn ns
ns.reduce{ |a, b| gcd2 a, b }
end
diff --git a/gcd.rs b/gcd.rs
index 95cc865..0925368 100644
--- a/gcd.rs
+++ b/gcd.rs
@@ -1,7 +1,17 @@
-use std::env;
+// Synopsis:
+//
+// $ rustc gcd.rs -o gcd-rs
+// $ ./gcd-rs 11 22 33 121
+// 11
+//
-fn gcd2(mut a: u64, mut b: u64) -> u64 {
- while b != 0 {
+use std::{cmp, env, ops};
+
+fn gcd2<T>(mut a: T, mut b: T) -> T
+where
+ T: cmp::PartialEq + Copy + ops::Rem<Output = T> + ops::Neg<Output = T>,
+{
+ while b != -b {
let c = b;
b = a % b;
a = c;
@@ -10,11 +20,17 @@ fn gcd2(mut a: u64, mut b: u64) -> u64 {
a
}
-fn main() {
- // XXX skip(1) to skip program name:
- let nums = env::args().skip(1).map(|s| s.parse().unwrap());
+fn gcdn<T>(nums: impl IntoIterator<Item = T>) -> Option<T>
+where
+ T: cmp::PartialEq + Copy + ops::Rem<Output = T> + ops::Neg<Output = T>,
+{
+ nums.into_iter().reduce(gcd2)
+}
- let gcd = nums.fold(0, gcd2);
+fn main() {
+ let nums = env::args().skip(1).map(|s| s.parse::<i64>().unwrap());
- println!("{}", gcd);
+ if let Some(gcd) = gcdn(nums) {
+ println!("{gcd}");
+ }
}
diff --git a/gcd.sh b/gcd.sh
index 9548b1d..b956286 100755
--- a/gcd.sh
+++ b/gcd.sh
@@ -16,5 +16,7 @@ gcdn() {
echo $r
}
-gcdn $*
+if test $# -gt 0 ; then
+ gcdn $*
+fi