{ "cells": [ { "cell_type": "markdown", "id": "0335593b-f5d8-4935-b52d-8d92f04664c0", "metadata": {}, "source": [ "This notebook explores computations with Julia, in particular with regards to interfacing." ] }, { "cell_type": "markdown", "id": "cc7d2149-0711-4fe7-b719-849ee43d8192", "metadata": {}, "source": [ "# 1. PyCall" ] }, { "cell_type": "markdown", "id": "29f5ee74-2d10-492c-afc3-02383628171f", "metadata": {}, "source": [ "Although there may not be any need for in Julia, because of `LinearAlgebra`, if we wanted to, we could use numpy through the installed package in the Python interpreter." ] }, { "cell_type": "code", "execution_count": 6, "id": "250d1eb0-369a-43d4-9706-542efe98b8f4", "metadata": { "tags": [] }, "outputs": [], "source": [ "using PyCall" ] }, { "cell_type": "code", "execution_count": 7, "id": "1d88c3aa-5a81-4ba5-ba48-1a2ed8f37826", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "PyObject " ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np = pyimport(\"numpy\")" ] }, { "cell_type": "code", "execution_count": 8, "id": "729f2536-c892-4da0-8432-a41c44246513", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "0.5403023058681398" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.cos(1)" ] }, { "cell_type": "markdown", "id": "88a00ba2-441b-49f9-8ed8-edccf3355161", "metadata": {}, "source": [ "The above statements show that `numpy` was installed and that we can use `numpy` via `PyCall`, calling the Python interpreter." ] }, { "cell_type": "markdown", "id": "44cdf778-e6eb-4a4c-b44e-911de0d53545", "metadata": {}, "source": [ "# 2. Adding the current directory to the Python path" ] }, { "cell_type": "markdown", "id": "aeaeb400-6ec3-42bd-9bde-670d85f5d5fb", "metadata": {}, "source": [ "We can call our Python functions in a Julia session." ] }, { "cell_type": "code", "execution_count": 9, "id": "aa546eec-c005-4464-9912-cb9edccc7040", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "PyObject ['/home/jan/Courses/MCS507/Fall23/Lec10', '/home/jan/miniconda3/lib/python310.zip', '/home/jan/miniconda3/lib/python3.10', '/home/jan/miniconda3/lib/python3.10/lib-dynload', '/home/jan/miniconda3/lib/python3.10/site-packages']" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pushfirst!(PyVector(pyimport(\"sys\")[\"path\"]), @__DIR__)" ] }, { "cell_type": "code", "execution_count": 10, "id": "396035ae-eac4-4ee5-a957-27bb31f4cd22", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "PyObject " ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "hello = pyimport(\"hellopython\")" ] }, { "cell_type": "code", "execution_count": 11, "id": "858f388b-ecdb-4c5f-80f0-39f624673fa7", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Python says hello!\n" ] } ], "source": [ "hello.say_hello()" ] }, { "cell_type": "markdown", "id": "f0c23740-e470-47e1-85eb-a3a41046e3e8", "metadata": {}, "source": [ "# 3. Calling qsort of C" ] }, { "cell_type": "markdown", "id": "f353171b-a7da-4183-9757-80ffebd20d93", "metadata": {}, "source": [ "We will wrap the C function qsort.\n", "\n", "```\n", " void qsort(void *base, size_t nmemb, size_t size,\n", " int (*compare)(const void*, const void*));\n", "```\n", "\n", "The C qsort needs a callback function `compare`,\n", "to define the order between the elements to be sorted." ] }, { "cell_type": "code", "execution_count": 12, "id": "d54fca53-5d05-476e-832e-2e79301fd236", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "mycompare" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"\n", " mycompare(a, b)\n", "\n", "Comparison function (Julia) to pass to qsort (C).\n", "\"\"\"\n", "function mycompare(a, b)::Cint\n", " return (a < b) ? -1 : ((a > b) ? +1 : 0)\n", "end" ] }, { "cell_type": "markdown", "id": "5f1dbbd9-e854-4853-842f-cc4d3542b3d4", "metadata": {}, "source": [ "To pass this Julia function to C,\n", "we use the macro `@function`." ] }, { "cell_type": "code", "execution_count": 13, "id": "f36229f1-ba56-4eb7-8209-09054d551b8c", "metadata": { "tags": [] }, "outputs": [], "source": [ "mycompare_c = @cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble}));" ] }, { "cell_type": "code", "execution_count": 14, "id": "b514b56a-c468-4e5d-86a5-050c0cac4e81", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A random sequence of numbers :\n", "[0.2940687736409139; 0.5978945007534073; 0.6994734515115479; 0.5461125690644831; 0.38085964114559967; 0.34595010533944537; 0.4373844662812475; 0.3676769993216489; 0.5535536572840571; 0.5341432251110406; 0.6944491763139657; 0.7508549891732916; 0.3093877589932401; 0.9843509338778118; 0.5476732840584834; 0.06762735151607191;;]\n", "Calling qsort ...\n", "The sorted sequence :\n", "[0.06762735151607191; 0.2940687736409139; 0.3093877589932401; 0.34595010533944537; 0.3676769993216489; 0.38085964114559967; 0.4373844662812475; 0.5341432251110406; 0.5461125690644831; 0.5476732840584834; 0.5535536572840571; 0.5978945007534073; 0.6944491763139657; 0.6994734515115479; 0.7508549891732916; 0.9843509338778118;;]\n" ] } ], "source": [ "println(\"A random sequence of numbers :\")\n", "A = rand(16, 1)\n", "println(A)\n", "\n", "println(\"Calling qsort ...\")\n", "\n", "ccall(:qsort, Cvoid, (Ptr{Cdouble}, Csize_t, Csize_t, Ptr{Cvoid}),\n", " A, length(A), sizeof(eltype(A)), mycompare_c)\n", "\n", "println(\"The sorted sequence :\")\n", "println(A)" ] }, { "cell_type": "markdown", "id": "63af10d0-6d59-461d-82fc-2409c7d550c3", "metadata": {}, "source": [ "# 4. String Conversions" ] }, { "cell_type": "markdown", "id": "c4528c89-1918-4049-8bf4-aa49754909ef", "metadata": {}, "source": [ "This section illustrates the allocation and the conversion\n", "of a C pointer to a Julia string." ] }, { "cell_type": "code", "execution_count": 15, "id": "adefa202-6b26-4d0b-86bc-0726057dd225", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "gethostname" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"\n", " function gethostname()\n", "\n", "Allocates memory for the hostname first\n", "and the converts the pointer to a Julia string.\n", "\"\"\"\n", "function gethostname()\n", " hostname = Vector{UInt8}(undef, 128)\n", " # ccall((:gethostname, \"libc\"), Int32,\n", " ccall(:gethostname, Int32,\n", " (Ptr{UInt8}, Csize_t),\n", " hostname, sizeof(hostname))\n", " hostname[end] = 0; # ensure null-termination\n", " return unsafe_string(pointer(hostname))\n", "end" ] }, { "cell_type": "code", "execution_count": 16, "id": "cedf0828-85be-405f-80cf-6a16476e43cf", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "\"Ada\"" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "name = gethostname()\n", "name" ] }, { "cell_type": "markdown", "id": "9325d687-10e3-410a-8851-f13e11e21894", "metadata": {}, "source": [ "# 5. Running a Pipeline" ] }, { "cell_type": "markdown", "id": "dd67a8de-6133-4d14-b810-210bfabcb25b", "metadata": {}, "source": [ "Calling a program at the command line via another program:\n", "\n", "1. prepare the input file\n", "\n", "2. direct the input to the program, redirect the output to a file\n", "\n", "3. process the output file" ] }, { "cell_type": "markdown", "id": "5e961f18-b1e5-40fe-a32a-10c0eb57a0ed", "metadata": {}, "source": [ "The code below illustrates a pipeline to list the names of\n", "the Julia scripts in the current directory." ] }, { "cell_type": "code", "execution_count": 17, "id": "f8c91e7b-4128-469a-a086-4aabd55b8b5f", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "Base.ProcessChain(Base.Process[Process(`\u001b[4mls\u001b[24m`, ProcessExited(0)), Process(`\u001b[4mgrep\u001b[24m \u001b[4m.jl\u001b[24m`, ProcessExited(0))], Base.DevNull(), Base.DevNull(), Base.DevNull())" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "run(pipeline(`ls` ,\n", " pipeline(`grep \".jl\"`, stdout=\"listing.txt\")))" ] }, { "cell_type": "code", "execution_count": 18, "id": "6fe4348b-7014-4bde-8716-41528958b62f", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "IOStream()" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "outputfile = open(\"listing.txt\", \"r\")" ] }, { "cell_type": "code", "execution_count": 19, "id": "dfa191d1-0bf0-4de0-bbd7-af05b547ee25", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Julia scripts in current directory :\n", "callqsort.jl\n", "pipe4ls.jl\n", "polyroots.jl\n", "polyrootscall.jl\n", "showhostname.jl\n" ] } ], "source": [ "lines = readlines(outputfile)\n", "println(\"Julia scripts in current directory :\")\n", "for i=1:length(lines)\n", " println(lines[i])\n", "end" ] }, { "cell_type": "markdown", "id": "4faaf54c-cc8a-4560-891a-c609e83c668c", "metadata": {}, "source": [ "This construction is applied in the `polyrootscall.jl` program." ] } ], "metadata": { "kernelspec": { "display_name": "Julia 1.9.3", "language": "julia", "name": "julia-1.9" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.9.3" } }, "nbformat": 4, "nbformat_minor": 5 }