Kumite (ko͞omiˌtā) is the practice of taking techniques learned from Kata and applying them through the act of freestyle sparring.
You can create a new kumite by providing some initial code and optionally some test cases. From there other warriors can spar with you, by enhancing, refactoring and translating your code. There is no limit to how many warriors you can spar with.
A great use for kumite is to begin an idea for a kata as one. You can collaborate with other code warriors until you have it right, then you can convert it to a kata.
Fortran Procedures - Subroutines
In a previous Kumite, I mentioned that there are two types of procedures in Fortran:
- Functions - These evaluate to a given value which is returned to the caller (for further computation by other parts of the program, for example)
- Subroutines - These only perform a set of actions and do not evaluate to any value
This Kumite aims to demonstrate how to define and invoke a Fortran subroutine.
A Fortran subroutine is in fact declared/defined in the same way as a function except the function
keyword (in both the first and last lines) are replaced with subroutine
. Pretty much everything else that holds for functions also holds for subroutines, with the exception of a lack of return value (and therefore result(<res_var>)
annotation is not permitted). You can even declare a subroutine as recursive
(and/or even pure
)!
module Solution
implicit none
contains
recursive subroutine print1ToN(n)
integer :: n
if (n > 0) then
call print1ToN(n - 1) ! NOTE: See explanation below code example
print "(I0)", n
end if
end subroutine print1ToN
end module Solution
When invoking a subroutine, the syntax is slightly different - you have to add the call
keyword in front of the subroutine name, like such:
program TestCases
use Solution
implicit none
call print1ToN(10)
! > 1
! > 2
! > ... (you get the idea ;) )
! > 10
end program TestCases
module Solution
implicit none
contains
recursive subroutine print1ToN(n)
integer :: n
if (n > 0) then
call print1ToN(n - 1) ! NOTE: See explanation below code example
print "(I0)", n
end if
end subroutine print1ToN
end module Solution
program TestCases
use CW2
use Solution
implicit none
print "(A21)", "Printing 1 to 10 ... "
call print1ToN(10)
print "(A22)", "Printing 1 to 100 ... "
call print1ToN(100)
! I could probably somehow test the output to STDOUT by messing with file handles and such
! but for simplicity, let's just give my recursive subroutine a free pass ;)
call assertEquals(.true., .true.)
end program TestCases
Interfacing
In Fortran modules, it is possible to "overload" a prodecure with several variants, each accepting different types/numbers of arguments through interfacing. An interface is essentially a named alias to one or more defined procedures. For example, when we first introduced functions, our add
function was only capable of accepting two default (32-bit) integers and compute its sum (as a 32-bit integer). What if we wanted our add
function to work on reals as well? Or complex numbers? In that case, all we have to do is to define three separate functions and implement them accordingly - let's call them addIntegers
, addReals
and addComplexNumbers
. After that, we alias them all under the same name add
through interfacing which is achieved by using the interface
keyword and has the following syntax (ALL_CAPS
denote placeholders):
interface ALIAS_NAME
module procedure PROC_1, PROC_2, ..., PROC_N
end interface ALIAS_NAME
The interface is always placed at the top section of the module, i.e. before the contains
keyword:
module InterfacingExample
implicit none
! Our interface
interface add
! The `addIntegers`, `addReals` and `addComplexNumbers`
! functions should all be aliased number the name `add`
module procedure addIntegers, addReals, addComplexNumbers
end interface add
contains
pure function addIntegers(a, b) result(c)
integer, intent(in) :: a, b
integer :: c
c = a + b
end function addIntegers
pure function addReals(a, b) result(c)
real, intent(in) :: a, b
real :: c
c = a + b
end function addReals
pure function addComplexNumbers(a, b) result(c)
complex, intent(in) :: a, b
complex :: c
c = a + b
end function addComplexNumbers
end module InterfacingExample
Now let's test it in our program:
program Main
use InterfacingExample
implicit none
print *, add(1, 2) ! > 3 (perhaps with padding)
print *, add(3.5, 4.5) ! > 8.0 (perhaps with padding)
print *, add(cmplx(3, -4), cmplx(2, 1)) ! > (5.0, -3.0) (perhaps with padding)
end program Main
Our alias works as expected. However, at this point, you might be wondering if the functions are still accessible through their original names (e.g. addIntegers
). If that is the case then your doubts are well-founded - the functions are still accessible through their original names (which may not be desirable). To hide the original names of the functions and expose only the alias, simply declare the original function names as private
the same way you would variables/constants:
module InterfacingExample
implicit none
private :: addIntegers, addReals, addComplexNumbers
! Our interface
interface add
! The `addIntegers`, `addReals` and `addComplexNumbers`
! functions should all be aliased number the name `add`
module procedure addIntegers, addReals, addComplexNumbers
end interface add
contains
pure function addIntegers(a, b) result(c)
integer, intent(in) :: a, b
integer :: c
c = a + b
end function addIntegers
pure function addReals(a, b) result(c)
real, intent(in) :: a, b
real :: c
c = a + b
end function addReals
pure function addComplexNumbers(a, b) result(c)
complex, intent(in) :: a, b
complex :: c
c = a + b
end function addComplexNumbers
end module InterfacingExample
module InterfacingExample
implicit none
private :: addIntegers, addReals, addComplexNumbers
! Our interface
interface add
! The `addIntegers`, `addReals` and `addComplexNumbers`
! functions should all be aliased number the name `add`
module procedure addIntegers, addReals, addComplexNumbers
end interface add
contains
pure function addIntegers(a, b) result(c)
integer, intent(in) :: a, b
integer :: c
c = a + b
end function addIntegers
pure function addReals(a, b) result(c)
real, intent(in) :: a, b
real :: c
c = a + b
end function addReals
pure function addComplexNumbers(a, b) result(c)
complex, intent(in) :: a, b
complex :: c
c = a + b
end function addComplexNumbers
end module InterfacingExample
program Main
use CW2
use InterfacingExample
implicit none
call describe("add")
call it("adds integers")
call assertEquals(2, add(1, 1))
call assertEquals(8, add(3, 5))
call assertEquals(108689, add(19392, 89297))
call endContext()
call it("adds reals")
call assertWithinTolerance(3.5, add(1.3, 2.2), 1e-3)
call assertWithinTolerance(17.4, add(6.1, 11.3), 1e-3)
call assertWithinTolerance(-3.7, add(4.9, -8.6), 1e-3)
call endContext()
call it("adds complex numbers")
call assertWithinTolerance(cmplx(5, -3), add(cmplx(3, -4), cmplx(2, 1)), 1e-3)
call assertWithinTolerance(cmplx(-2.1, -7.7), add(cmplx(7.7, 2.1), cmplx(-9.8, -9.8)), 1e-3)
call assertWithinTolerance(cmplx(0, 0), add(cmplx(-3, 4), cmplx(3, -4)), 1e-3)
call endContext()
call endContext()
! Try these - they won't work ;)
! print *, addIntegers(1, 2)
! print *, addReals(3.3, 4.4)
! print *, addComplexNumbers(cmplx(1, 2), cmplx(3, 4))
end program Main
Just a simple C function void say_hello()
written in NASM v2.11.x which prints Hello World!
to the console.
global say_hello
section .text
say_hello:
mov eax, 4 ; system call for write (for Linux)
mov ebx, 1 ; file handle 1 is STDOUT
mov ecx, message ; memory address of output buffer
mov edx, msgLen ; size of output buffer in bytes
int 0x80 ; invoke OS to do the write
ret ; Return to the caller
section .data ; Read-only data
message db "Hello World!", 10 ; message = "Hello World!\n"
msgLen equ $-message ; msgLen = strlen(message)
#include <criterion/criterion.h>
void say_hello();
Test(say_hello, should_print_hello_world) {
say_hello();
cr_assert(1);
}
Operator Overloading
In Fortran, operator overloading is done via interfacing. The syntax is almost identical to overloading procedures except the name of the alias is replaced by operator (OPERATOR)
(where OPERATOR
is a placeholder for the actual operator).
Unlike some programming languages such as Haskell, operators to be overloaded cannot contain arbitrary symbols (or a sequence thereof). Only the following operators and types of operators can be overloaded/defined:
- Symbol / symbol combinations already defined as operators in Fortran (e.g.
+
,-
,*
,/
,==
,/=
, etc.) -
.OPERATOR_NAME.
whereOPERATOR_NAME
may only contain English letters (not even numbers, not even underscore)
Operators can be unary or binary or both (of the form OPERATOR OPERAND
or OPERAND_1 OPERATOR OPERAND_2
) depending on whether the function(s) implementing it accept one or two arguments. However, for operators intrinsic to Fortran (such as *
or /
), the functions implemeting their overloads may only accept as many arguments as they were originally defined (e.g. you cannot overload *
to accept only one operand).
Note that operators must be pure in Fortran, i.e. they are not permitted to mutate their operands. Therefore, functions implementing the overloaded operator must be declared pure
(or if not, at least all input parameters must be declared intent(in)
).
module OperatorOverloading
implicit none
private :: realRecip, cmplxRecip ! Hide implementation details of overloaded operator
interface operator (.recip.) ! Operator for finding the reciprocal
! (i.e. multiplicative inverse) of a number
module procedure realRecip, cmplxRecip
end interface
contains
pure function realRecip(x)
real, intent(in) :: x
real :: realRecip
realRecip = 1.0 / x
end function realRecip
pure function cmplxRecip(z)
complex, intent(in) :: z
complex :: cmplxRecip
cmplxRecip = cmplx(1, 0) / z
end function cmplxRecip
end module OperatorOverloading
program TestCases
use CW2
use OperatorOverloading
implicit none
call describe(".recip.")
call it("should find the reciprocal of real numbers")
call assertWithinTolerance(1.0 / 3.0, .recip. 3.0, 1e-3)
call assertWithinTolerance(1.0 / 1.2945, .recip. 1.2945, 1e-3)
call assertWithinTolerance(1.0 / 0.017, .recip. 0.017, 1e-3)
call endContext()
call it("should find the reciprocal of complex numbers")
call assertWithinTolerance(cmplx(1, 0) / cmplx(3, 4), .recip. cmplx(3, 4), 1e-3)
call assertWithinTolerance(cmplx(1, 0) / cmplx(-2.1, -0.9), .recip. cmplx(-2.1, -0.9), 1e-3)
call assertWithinTolerance(cmplx(1, 0) / cmplx(0.07, 0.08), .recip. cmplx(0.07, 0.08), 1e-3)
call endContext()
call endContext()
end program
Pointers
Fortran has basic support for pointers. A pointer is a rather primitive type of reference - it is essentially a memory address (associated with a given type) which is said to "point to" the data it is referencing. Unlike C/C++/ObjC, Fortran does not support pointers to pointers, function pointers, arrays of pointers or pointer arithmetic but it is still sufficient to allow us to define simple recursive datatypes such as linked lists or binary trees.
To declare a pointer:
integer, pointer :: p ! `p` is a non-associated integer pointer
To associate a pointer to a target:
! The `target` annotation is required for a pointer to point to it
! Otherwise, `n` is just another ordinary integer
integer, target :: n = 42
integer, pointer :: p => n ! `p` is now associated with `n`
To dereference a pointer:
integer, target :: n = 42
integer, pointer :: p => n ! `p` points to `n`
p = 100 ! `p` is automatically dereferenced and its target `n` set to 100
To associate a pointer to another target:
integer, target :: m = 100, n = 42
integer, pointer :: p => n ! `p` points to `n`
p => m ! `p` now points to `m` instead
To make two (or more) pointers point to the same target:
integer, target :: n = 42
integer, pointer :: p1, p2
p1 => n ! `p1` points to `n`
p2 => p1 ! `p2` now points to the TARGET of `p1` which is `n`
! REMEMBER: `p2` does NOT point to `p1` - pointers
! to pointers are not permitted in Fortran
To define a null pointer (i.e. one that does not reference any data):
integer, pointer :: p => null()
To allocate memory for a pointer instead of pointing it to a pre-existing target:
integer, pointer :: p
allocate(p) ! Allocate memory under pointer (just sufficient for one integer)
! Do something with `p`. Make sure `p` doesn't point to anything else
! before it is deallocated (otherwise a memory leak will occur)!
deallocate(p) ! Free the memory under the pointer
To check whether a pointer is associated with a target:
associated(p) ! Checks whether `p` is associated with a target
! Evaluates to the corresponding logical value
! (.true. if associated, .false. otherwise)
The main code example in this Kumite involves derived data types.
module Pointers
implicit none
type Node ! A node of a singly linked list
integer :: data
type(Node), pointer :: next
end type Node
end module Pointers
program TestCases
use CW2
use Pointers
implicit none
type(Node), pointer :: oneTwoThree
type(Node), target :: nd1, nd2, nd3
nd3%data = 3
nd3%next => null()
nd2%data = 2
nd2%next => nd3
nd1%data = 1
nd1%next => nd2
oneTwoThree => nd1 ! oneTwoThree <- (1 -> 2 -> 3 -> null())
print "(A63)", "Printing out the contents of our linked list `oneTwoThree` ... "
do while (associated(oneTwoThree))
print "(I0)", oneTwoThree%data
oneTwoThree => oneTwoThree%next
end do
print "(A19)", "End of list reached"
call assertEquals(.true., .true.) ! free pass ;)
end program TestCases
Return "Hello World."
char* Hi (void)
{
return("Hello World.");
}
// TODO: Replace examples and use TDD development by writing your own tests. The code provided here is just a how-to example.
#include <criterion/criterion.h>
// replace with the actual method being tested
char* Hi ();
Test(the_multiply_function, should_pass_all_the_tests_provided) {
cr_assert_eq(Hi(""), "Hello World.");
}
global trunc_
section .text
trunc_:
cvttsd2si eax, xmm0
ret
#include <criterion/criterion.h>
int trunc_(double);
Test(add_test, should_add_integers) {
cr_assert_eq(trunc_(1.2), 1);
cr_assert_eq(trunc_(1.8), 1);
cr_assert_eq(trunc_(-1.2), -1);
cr_assert_eq(trunc_(-1.8), -1);
}
#include <utility>
std::pair<int, int> foo() {
return {0, 0};
}
#include <utility>
Describe(function_foo)
{
It(should_return_1_1)
{
Assert::That(foo(), Equals(std::pair<int, int>{1, 1}));
}
};
Dynamic Memory Allocation by using C library malloc() function
It is possible to allocate memory dynamically in NASM (obviously, otherwise how would it be possible in C and other higher-level languages?) and the easiest way to do it is probably by relying on the C library function malloc()
.
global one_two_three
extern malloc ; C library function malloc()
section .text
one_two_three:
mov rdi, 12 ; size_t bytes_required = 3 * sizeof(int) == 12 (because sizeof(int) == 4 on CW)
call malloc ; int *result = malloc(bytes_required)
mov dword [rax], 1 ; result[0] = 1 (`dword` means "double word" where 1 word = 2 bytes)
mov dword [rax + 4], 2 ; result[1] = 2
mov dword [rax + 8], 3 ; result[2] = 3
ret ; return result
#include <criterion/criterion.h>
int *one_two_three(void);
Test(the_one_two_three_function, should_return_a_dynamically_allocated_array_of_one_two_three) {
int *a = one_two_three();
cr_assert_eq(a[0], 1);
cr_assert_eq(a[1], 2);
cr_assert_eq(a[2], 3);
free(a);
}
This Kumite is created to test JQuery support on Codewars.
var jsdom = require("jsdom/lib/old-api.js");
jsdom.env(
'<!DOCTYPE html><p>Hello world</p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a>', ["http://code.jquery.com/jquery.js"],
function(err, window) {
console.log(window.document.querySelector("p").textContent);
var $ = window.$;
$.getJSON('https://www.codewars.com/users/Javatlacati', null, function(data) {
console.log(data);
}).error(function(e) {
console.log("first attempt failed\n" + JSON.stringify(e));
});
var name = "kazk";
var url = "http://anyorigin.com/go?url=" + encodeURIComponent("https://www.codewars.com/users/") + name + "&callback=?";
$.get(url, function(response) {
console.log(response);
}).error(function(e) {
console.log("second attempt failed\n" + JSON.stringify(e));
});
console.log("contents of a.the-link:", window.$("a.the-link").text());
}
);