fortran66のブログ

fortran について書きます。

【メモ帳】Fortran で Mac SwiftUI 利用

AI 様に Fortran から Mac SwiftUI 利用してもらう

MacGUI がどうなっているのか全く知らないのですが、古い Objective C 時代のものと、新しい SwiftUI のものがあるらしいというのは噂に聞いています。

ChatGPT4o に fortran から SwiftUI 使えるか?と聞いたところ、C インターフェースかますことで出来るということで、簡単な例を作ってくれました。swift で DLL を作り Fortran からそれを呼びます。ほぼ無修正で動作しました。AI スンバラすい!

実行結果

% swiftc -emit-library -o libText.dylib text.swift -Xlinker -install_name -Xlinker @rpath/libText.dylib
% gfortran -o text text.f90 -L. -lText                                                                 
% ./text

ソース・プログラム

import Cocoa
import SwiftUI

@_cdecl("startSwiftUIWithMessage")
public func startSwiftUIWithMessage(message: UnsafePointer<CChar>) {
    let messageString = String(cString: message)
    if #available(macOS 10.15, *) {
        let app = NSApplication.shared
        let delegate = AppDelegate(message: messageString)
        app.delegate = delegate
        app.run()
    }
}

@available(macOS 10.15, *)
class AppDelegate: NSObject, NSApplicationDelegate {
    var window: NSWindow!
    var message: String

    init(message: String) {
        self.message = message
    }

    func applicationDidFinishLaunching(_ notification: Notification) {
        let contentView = ContentView(message: message)

        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .resizable, .miniaturizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.isReleasedWhenClosed = false
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }

    func applicationWillTerminate(_ notification: Notification) {
        // Cleanup code
    }
}

struct ContentView: View {
    var message: String

    var body: some View {
        Text(message)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}
program call_swiftui
  use iso_c_binding
  implicit none

  interface
    subroutine startSwiftUIWithMessage(message) bind(C, name="startSwiftUIWithMessage")
      import :: c_char
      character(kind=c_char), intent(in) :: message(*)
    end subroutine startSwiftUIWithMessage
  end interface

  character(len=100) :: message

  ! Set the message to be passed to SwiftUI
  message = "Hello from Modern Fortran!"

  ! Call the SwiftUI function with the message
  call startSwiftUIWithMessage(trim(adjustl(message))//c_null_char)

end program call_swiftui

【メモ帳】Windows Intel Fortran で GDI+ による画像ファイル(jpg/png/gif/etc)読み書き

Windows GDI+ API 呼び出しによる画像ファイル読み書き

Win32/64API の GDI では BMP ファイルの読み書きしかできませんでしたが、その後に出た GDI+ で JPG/PNG/GIF/TIFF 等が読み書きできるようになりました。しかしながら C++ のクラス利用などが前提となって GDI の時の様に素朴に C ルーチン呼び出しのインターフェースを書くだけでは利用できず、私にはお手上げでした。

その後、昔から Fortran での画像処理を手掛けていた Fortran Plaza さんが、gfortran から GDI+ を利用できることを示してソースコードも公開されました。その内容はライブラリ全体を包括するような本格的なもので、大規模で少し難しく、そのうち勉強しようと思いつつほったらかしていました。

fortran66.hatenablog.com

最近、AI に 「GDI+ での jpg 読み書き Fortran プログラム書けるか?」と聞いてみたところ、「お安い御用さ!」と言いつつ、ホイホイプログラムを吐き出し、画像サイズを出すところまではわずかな修正で行けました。そこから先は嘘だらけになって若干苦労しましたが、必要最低限の API インターフェースの用意で、JPG/PNG/GIF/TIFF 等の画像ファイルを RGB 形式の配列として読み込み、適当な処理をした後、JPG/PNG/GIF/TIFF 等の好みの形式で書き出せるようになりました。

かったるい C との interface 書きなどを AI がやってくれるので、AI 様様と言ったところです。ただ AI 様は、質問者の私がよく分からないことを、分からない人なりの要領を得ない問で聞くと、嘘と真を混ぜて答えてきて閉口させられます。こちらも真偽の判断がつかないので、すぐ騙されます。この辺は、次の世代の AI を待ちたいと思います。

AI 利用は 八合目あたりまで AI 様のケーブルカーで登って、そこから頂上までは自力登山という感じでしょうか。最近の腐りきった Google 検索などではなかなか欲しい情報にたどり着けないので 、AI 様なしではこのプログラムは書けなかったと思います。なおもっぱら Claude 無料枠に書いてもらいました。ChatGPT をクロスチェックに利用しました。

実行例

jpg ファイルを読み込んで、色を反転させて別名 jpg ファイルに保存しています。

 GDI+ initialized successfully
 Image loaded successfully
           0 width         1280
           0 height         720
 Image saved successfully
 Bitmap disposed successfully
 GDI+ shut down successfully
 GDI+ library unloaded successfully
続行するには何かキーを押してください . . .

入力ファイル

出力ファイル


www.youtube.com

ソース・プログラム

intel fortran ifx 2024.2.0 で実行しました。stdcall などの呼び出し規約の関係で Win64 でなければ動きません。

ファイルの読み込みの方は、拡張子で自動判別して読み込めますが、書き込みの方は jpg 決め打ちになっています。CLSID を変えることで書き出しファイル形式を変えられます。(CLSID は ID 数列を 32bit little endian, 16 bit little endian, 16 bit little endian, 8bit/4bit の並びで解釈します。AIに騙されましたw)ファイル名は末尾に C 言語式の NULL 番兵が必要です。また ASCII 文字列では駄目で、16bit の wide 文字列に変換する必要があります。(AIに騙されましたw)

プログラムの概要:

  1. gdiplus.dll をダイナミックロード。
  2. CreateBitmapFromFile によって 32bit BMP 形式(ARGB 形式)で読み込む。
  3. RGB の配列をいじる。
  4. GdipSaveImageToFile でファイルに書き出す。
module LoadDll_m
    use, intrinsic :: iso_c_binding
    implicit none
    private
    public :: LoadLibrary, GetProcAddress, FreeLibrary
    ! Windows API functions ; load DLL
    interface
        function LoadLibrary(lpFileName) bind(C, name='LoadLibraryA')
            import
            integer(C_INTPTR_T) :: LoadLibrary
            character(kind=C_CHAR), intent(in) :: lpFileName(*)
        end function LoadLibrary

        function GetProcAddress(hModule, lpProcName) bind(C, name='GetProcAddress')
            import
            type(C_FUNPTR) :: GetProcAddress
            integer(C_INTPTR_T), value :: hModule
            character(kind=C_CHAR), intent(in) :: lpProcName(*)
        end function GetProcAddress

        function FreeLibrary(hModule) bind(C, name='FreeLibrary')
            import
            integer(C_INT) :: FreeLibrary
            integer(C_INTPTR_T), value :: hModule
        end function FreeLibrary
    end interface    
end module LoadDll_m
    
module WideString_m
    use, intrinsic :: iso_c_binding
    implicit none
    ! Windows API constants for multibyte-to-wide
    integer(C_INT), parameter :: CP_ACP = 0
    integer(C_INT), parameter :: MB_ERR_INVALID_CHARS = z'00000008'
    ! Interface for MultiByteToWideChar
    interface
        function MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, &
                                     lpWideCharStr, cchWideChar) bind(C, name='MultiByteToWideChar')
            import
            integer(C_INT), value :: CodePage, dwFlags
            type(C_PTR), value :: lpMultiByteStr
            integer(C_INT), value :: cbMultiByte
            type(C_PTR), value :: lpWideCharStr
            integer(C_INT), value :: cchWideChar
            integer(C_INT) :: MultiByteToWideChar
        end function MultiByteToWideChar
    end interface

    contains
    
    function to_wide_string(text) result(res)
        character(len = *), intent(in), target :: text
        character(kind=C_CHAR, len=:), allocatable, target :: res
        integer(C_INT) :: len_text, iret
        character(kind=C_CHAR, len=:), pointer :: wide_string
         
        len_text = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &
                                       c_loc(text), len_trim(text), &
                                       C_NULL_PTR, 0)
        if (len_text == 0) then
            print *, "to_wide_string: Error in getting length." !Error code:", GetLastError()
            stop
        end if

        ! Allocate the wide string return heap
        allocate(character(kind=C_CHAR, len=len_text*2) :: res)

        ! Convert the string
        iret = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &
                                   c_loc(text), len_trim(text), &
                                   c_loc(res), len_text)
        if (iret == 0) then
            print *, "to_wide_string: Error in conversion." ! Error code:", GetLastError()
            stop
        end if
    end function to_wide_string
end module WideString_m
    
module GdiPlus_m
    use, intrinsic :: iso_c_binding
    use :: LoadDll_m
    use :: WideString_m
    implicit none
    ! Bitmap Constants 
    integer(c_int), parameter :: PixelFormat32bppARGB = 2498570
    integer(c_int), parameter :: ImageLockModeRead = 1, ImageLockModeWrite = 2    

    ! GDI+ data types
    type, bind(C) :: GdiplusStartupInput_t
        integer(C_LONG) :: GdiplusVersion
        type(C_FUNPTR) :: DebugEventCallback
        integer(C_INT) :: SuppressBackgroundThread
        integer(C_INT) :: SuppressExternalCodecs
    end type GdiplusStartupInput_t
    
    ! Additional types
    type, bind(c) :: Rect_t
        integer(c_long) :: X = 0, Y = 0, Width = 0, Height = 0
    end type Rect_t
   
    type, bind(c) :: BitmapData_t
        integer(c_int) :: Width
        integer(c_int) :: Height
        integer(c_int) :: Stride
        integer(c_int) :: PixelFormat
        type(c_ptr) :: Scan0
        type(c_ptr) :: Reserved
    end type BitmapData_t

    ! GDI+ function pointer types
    abstract interface
        function GdiplusStartupFunc(token, input, output) bind(C)
            import
            integer(C_INT) :: GdiplusStartupFunc
            integer(C_INT64_T) :: token
            type(GdiplusStartupInput_t), intent(in) :: input
            type(C_PTR), value :: output
        end function GdiplusStartupFunc

        subroutine GdiplusShutdownFunc(token) bind(C)
            import
            integer(C_INT64_T), value :: token
        end subroutine GdiplusShutdownFunc

        function GdipLoadImageFromFileFunc(filename, image) bind(C)
            import
            integer(C_INT) :: GdipLoadImageFromFileFunc
            character(kind=C_CHAR), intent(in):: filename(*)
            type(C_PTR) :: image
        end function GdipLoadImageFromFileFunc

        function GdipSaveImageToFileFunc(image, filename, clsidEncoder, encoderParams) bind(C)
            import
            integer(C_long) :: GdipSaveImageToFileFunc
            type(C_PTR), value :: image
            character(kind=C_CHAR), intent(in) :: filename(*)
            type(C_PTR), value :: clsidEncoder
            type(C_PTR), value :: encoderParams
        end function GdipSaveImageToFileFunc
        
        function GdipGetImageWidthFunc(image, width) bind(c)
            import
            integer(c_long) :: GdipGetImageWidthFunc
            type(c_ptr), value :: image
            integer(c_int), intent(out) :: width
        end function GdipGetImageWidthFunc

        function GdipGetImageHeightFunc(image, height) bind(c)
            import
            integer(c_long) :: GdipGetImageHeightFunc
            type(c_ptr), value :: image
            integer(c_int), intent(out) :: height
        end function GdipGetImageHeightFunc
        
        function GdipDisposeImageFunc(image) bind(c)
            import
            integer(c_long) :: GdipDisposeImageFunc
            type(c_ptr), value :: image
        end function GdipDisposeImageFunc

        function GdipBitmapLockBitsFunc(bitmap, rect, flags, format, lockedBitmapData) bind(c)
            import
            integer(c_long) :: GdipBitmapLockBitsFunc
            type(c_ptr), value :: bitmap
            type(Rect_t), intent(in) :: rect
            integer(c_int), value :: flags
            integer(c_int), value :: format
            type(BitmapData_t) :: lockedBitmapData
        end function GdipBitmapLockBitsFunc

        function GdipBitmapUnlockBitsFunc(bitmap, lockedBitmapData) bind(c)
            import
            integer(c_long) :: GdipBitmapUnlockBitsFunc
            type(c_ptr), value :: bitmap
            type(BitmapData_t), intent(in) :: lockedBitmapData
        end function GdipBitmapUnlockBitsFunc
             
        function GdipCreateBitmapFromFileFunc(filename, bitmap) bind(c)
            import
            integer(c_long) :: GdipCreateBitmapFromFileFunc
            character(kind=C_CHAR), intent(in):: filename(*)
            type(c_ptr):: bitmap
        end function GdipCreateBitmapFromFileFunc
        
    end interface

    type(C_FUNPTR) :: procStartup, procShutdown 
    !
    type(C_FUNPTR) :: procLoadImage, procSaveImage
    type(c_funptr) :: procGetImageWidth, procGetImageHeight, procDisposeImage
    !
    type(c_funptr) :: procCreateBitmapFromFile
    type(c_funptr) :: procBitmapLockBits, procBitmapUnlockBits
    !
    procedure(GdiplusStartupFunc), pointer :: GdiplusStartup
    procedure(GdiplusShutdownFunc), pointer :: GdiplusShutdown
    !
    procedure(GdipLoadImageFromFileFunc), pointer :: GdipLoadImageFromFile
    procedure(GdipSaveImageToFileFunc), pointer :: GdipSaveImageToFile
    procedure(GdipGetImageWidthFunc), pointer :: GdipGetImageWidth
    procedure(GdipGetImageHeightFunc), pointer :: GdipGetImageHeight
    procedure(GdipDisposeImageFunc), pointer :: GdipDisposeImage
    !
    procedure(GdipCreateBitmapFromFileFunc), pointer :: GdipCreateBitmapFromFile
    procedure(GdipBitmapLockBitsFunc), pointer :: GdipBitmapLockBits
    procedure(GdipBitmapUnlockBitsFunc), pointer :: GdipBitmapUnlockBits
    !  
    !   CLSID
    !    {557CF400-1A04-11D3-9A73-0000F81EF32E}  bmp
    !    {557CF401-1A04-11D3-9A73-0000F81EF32E}  jpeg
    !    {557CF402-1A04-11D3-9A73-0000F81EF32E}  gif
    !    {557CF403-1A04-11D3-9A73-0000F81EF32E}  emf
    !    {557CF404-1A04-11D3-9A73-0000F81EF32E}  wmf
    !    {557CF405-1A04-11D3-9A73-0000F81EF32E}  tiff
    !    {557CF406-1A04-11D3-9A73-0000F81EF32E}  png
    !    {557CF407-1A04-11D3-9A73-0000F81EF32E}  icon
    integer(c_long), target :: clsid_bmp_encoder(4) = [z'557cf400', z'11d31a04', z'0000739a', z'2ef31ef8'] !bmp
    integer(c_long), target :: clsid_jpg_encoder(4) = [z'557cf401', z'11d31a04', z'0000739a', z'2ef31ef8'] !jpg
    integer(c_long), target :: clsid_gif_encoder(4) = [z'557cf402', z'11d31a04', z'0000739a', z'2ef31ef8'] !gif
    integer(c_long), target :: clsid_emf_encoder(4) = [z'557cf403', z'11d31a04', z'0000739a', z'2ef31ef8'] !emf
    integer(c_long), target :: clsid_wmf_encoder(4) = [z'557cf404', z'11d31a04', z'0000739a', z'2ef31ef8'] !wmf
    integer(c_long), target :: clsid_tif_encoder(4) = [z'557cf405', z'11d31a04', z'0000739a', z'2ef31ef8'] !tiff
    integer(c_long), target :: clsid_png_encoder(4) = [z'557cf406', z'11d31a04', z'0000739a', z'2ef31ef8'] !png
    integer(c_long), target :: clsid_ico_encoder(4) = [z'557cf407', z'11d31a04', z'0000739a', z'2ef31ef8'] !icon
    !
    integer(C_INTPTR_T) :: hLib
    integer(C_INT64_T) :: token
    type(GdiplusStartupInput_t) :: input
    !
    ! Bitmap
    type(BitmapData_t), target :: bmpData 
    type(c_ptr), target :: bitmap

    contains
    
    subroutine initialize_GDI()
        integer(C_INT) :: status
        ! Load the GDI+ library
        hLib = LoadLibrary("gdiplus.dll"//C_NULL_CHAR)
        if (hLib == 0) then
            print *, "Failed to load GDI+ library"
            stop
        end if

        ! Get the addresses of GDI+ functions
        procStartup = GetProcAddress(hLib, "GdiplusStartup"//C_NULL_CHAR)
        procShutdown = GetProcAddress(hLib, "GdiplusShutdown"//C_NULL_CHAR)
        !
        procLoadImage = GetProcAddress(hLib, "GdipCreateBitmapFromFile"//C_NULL_CHAR)
        procSaveImage = GetProcAddress(hLib, "GdipSaveImageToFile"//C_NULL_CHAR)
        procGetImageWidth = GetProcAddress(hLib, "GdipGetImageWidth"//C_NULL_CHAR)
        procGetImageHeight = GetProcAddress(hLib, "GdipGetImageHeight"//C_NULL_CHAR)
        procDisposeImage = GetProcAddress(hLib, "GdipDisposeImage"//C_NULL_CHAR)
        !
        procCreateBitmapFromFile = GetProcAddress(hLib, "GdipCreateBitmapFromFile"//C_NULL_CHAR)
        procBitmapLockBits = GetProcAddress(hLib, "GdipBitmapLockBits"//C_NULL_CHAR)
        procBitmapUnlockBits = GetProcAddress(hLib, "GdipBitmapUnlockBits"//C_NULL_CHAR)

        if (.not. c_associated(procStartup) .or. &
            .not. c_associated(procShutdown) .or. &
            .not. c_associated(procLoadImage) .or. &
            .not. c_associated(procSaveImage) .or. &
            .not. c_associated(procGetImageWidth) .or. &
            .not. c_associated(procGetImageHeight) .or. &
            .not. c_associated(procDisposeImage) .or. &
            .not. c_associated(procCreateBitmapFromFile) .or. &
            .not. c_associated(procBitmapLockBits) .or. & 
            .not. c_associated(procBitmapUnlockBits)  ) then
            print *, "Failed to get one or more GDI+ function addresses"
            status = FreeLibrary(hLib)
            stop
        end if

        ! Associate the C function pointers with the Fortran procedure pointers
        call c_f_procpointer(procStartup, GdiplusStartup)
        call c_f_procpointer(procShutdown, GdiplusShutdown)
        !
        call c_f_procpointer(procLoadImage, GdipLoadImageFromFile)
        call c_f_procpointer(procSaveImage, GdipSaveImageToFile)
        call c_f_procpointer(procGetImageWidth, GdipGetImageWidth)
        call c_f_procpointer(procGetImageHeight, GdipGetImageHeight)
        call c_f_procpointer(procDisposeImage, GdipDisposeImage)
        !
        call c_f_procpointer(procBitmapLockBits, GdipBitmapLockBits)
        call c_f_procpointer(procBitmapUnLockBits, GdipBitmapUnLockBits)
        call c_f_procpointer(procCreateBitmapFromFile, GdipCreateBitmapFromFile)
    
        ! Initialize GDI+ startup input
        input%GdiplusVersion = 1
        input%DebugEventCallback = C_NULL_FUNPTR
        input%SuppressBackgroundThread = 0
        input%SuppressExternalCodecs = 0

        ! Call GdiplusStartup
        status = GdiplusStartup(token, input, C_NULL_PTR)
        if (status /= 0) then
            print *, "Failed to initialize GDI+. Error code:", status
            status = FreeLibrary(hLib)
            stop
        else    
            print *, "GDI+ initialized successfully"
        end if
    end subroutine initialize_GDI
    
    subroutine finialize_GDI()
        integer(C_INT) :: status
        ! Shutdown GDI+
        call GdiplusShutdown(token)
        print *, "GDI+ shut down successfully"
        ! Unload the GDI+ library
        status = FreeLibrary(hLib)
        if (status == 0) then
            print *, "Failed to unload GDI+ library"
        else
            print *, "GDI+ library unloaded successfully"
        end if
    end subroutine finialize_GDI
    
    subroutine open_and_read(fn, pixels)
        character(kind=c_char, len=*), target, intent(in) :: fn
        integer(c_int), pointer, intent(out) :: pixels(:, :)
        !
        integer(C_INT) :: status
        integer(C_INT) :: iwidth, iheight
        type(Rect_t) :: rect_in
        !
        status = GdipCreateBitmapFromFile(to_wide_string(fn), bitmap)
        if (status /= 0) then
           print *, "Failed to load image. Error code:", status
           stop
        else
           print *, "Image loaded successfully"
           status = GdipGetImageWidth(bitmap, iwidth)
           print *, status, 'width ', iwidth    
           status = GdipGetImageHeight(bitmap, iHeight)
           print *, status, 'height', iheight     
        end if
        !
        bmpData%Width  = iwidth
        bmpData%Height = iheight
        bmpData%Stride = ((iwidth * 32 + 31) / 32) * 4
        bmpData%PixelFormat = PixelFormat32bppARGB
        ! Lock bitmap bits / c_null_ptr
        rect_in%X = 0
        rect_in%Y = 0
        rect_in%Width  = iwidth
        rect_in%Height = iheight
        !
        status = GdipBitmapLockBits(bitmap, rect_in, ImageLockModeRead + ImageLockModeWrite, &
                                    PixelFormat32bppARGB, bmpData)
        if (status /= 0) then
           print *, 'BitmapLockBits failed. status =', status 
           stop 
        end if 
        !
        ! bind to pixel data
        call c_f_pointer(bmpData%Scan0, pixels, [iwidth, iheight])
    end subroutine open_and_read
    
    subroutine write_and_close(fn)
        character(kind=c_char, len=*), intent(in) :: fn
        !
        integer(C_INT) :: status
        !
        status = GdipBitmapUnLockBits(bitmap, bmpData)
        if (status /= 0) then
           print *, 'BitmapUnLockBits failed. status =', status 
           stop
        end if 
        
        ! Save the image to a new file
        status = GdipSaveImageToFile(bitmap, to_wide_string(fn), C_loc(clsid_jpg_encoder), C_NULL_PTR)

        if (status /= 0) then
            print *, "Failed to save image. Error code:", status
        else
            print *, "Image saved successfully"
        end if
        ! Clean up
        status = GdipDisposeImage(bitmap)   
        if (status /= 0) then
            print *, "Failed to dispose Bitmap. Error code:", status
        else
            print *, "Bitmap disposed successfully"
        end if
    end subroutine write_and_close
end module GdiPlus_m


program test_gdiplus
    use, intrinsic :: iso_c_binding
    use :: LoadDll_m
    use :: GdiPlus_m
    implicit none
    
    call initialize_GDI() 
BMP:block    
        character(kind=c_char, LEN = 256), target :: fn
        integer(c_int), pointer :: pixels(:, :)
        ! load bmp/jpg/gif/png/... file as 32bit ARGB 2d-array      
        fn = "C:\temp\kositantan.jpg"//C_NULL_CHAR
        call open_and_read(fn, pixels)
        !
   RGBA:block 
            integer(c_int) :: ir, ig, ib, ia
            do concurrent (integer::ix = 1:size(pixels, 1), iy = 1:size(pixels, 2))
                ! Extract ARGB values
                ia = iand(ishft(pixels(ix, iy), -24), 255)
                ir = iand(ishft(pixels(ix, iy), -16), 255)
                ig = iand(ishft(pixels(ix, iy),  -8), 255)
                ib = iand(      pixels(ix, iy)      , 255)
                pixels(ix, iy) = (256 - ib) + 256 * (256 - ig + 256 * (256 - ir + 256 * ia))  
            end do
        end block RGBA
        ! 
        ! save as jpg   !  ( bmp/jpg/gif/png/... )       
        fn = "C:\temp\sika.jpg"//C_NULL_CHAR
        call write_and_close(fn)
    end block BMP
    call finialize_GDI()
end program test_gdiplus

【寝言】学士会報 第967号 第966号

966号

この号は大して面白くもなかったです。シェークスピアの話はちょっと良かったかな。

967号

この号は、初っ端から大爆笑できるオモシロ記事がありました。

最近、メディアで柯隆とかいう滑稽支那人が、中共の手先のような寝言をほざいているのをちょくちょく目にします。日本で高等教育を受けて、自由世界の情報に接し、餌まで与えてもらっているのに、なぜあんな異常な考えを持つのか不思議に思っていたのですが、その柯隆の講演会の記事があって、その中に答えと思われることが書いてありました。

柯隆は、64天安門事件のすぐ後の 1988 年、訳あって日本の愛知大学に入学することになったのですが、経済原論の授業に出たらマルクス経済学の授業で、そのせいで発狂したようです。

社会主義の中国を脱出し、資本主義の日本に来たのに、なぜマルクスを勉強しなければならないのか」と抗議すると、「愛知大学の経済原論は全部マル経です」と言われ、ショックを受けました。

これでは頭がおかしくなってもしょうがないですね。爆笑しました。

講演の結びでは、日本の大学は教育制度を改革しろとも主張しておりまして、この時のショックがまだ尾を引いているのかもしれません。アカの皆さん、うれしいですかw

【ニュース】Intel fortan 2024.2 出る!

Intel Fortran Compiler 2024.2.0

www.intel.com

リリースノートをみると、相変わらず OpenMP 関係に力を入れているようです。Fortran 2023 文法面での目立った進展なし。

www.intel.com

F1 HELP

Visual Studio の F1 HELP のセットアップが手動なのがだるい。

www.intel.com

ファイルを解凍して突っ込むディレクトリは

C:\Program Files (x86)\Intel\oneAPI\compiler\latest\share\documentation\en\compiler_f

【寝言】おっさんは泥 臭い汚い羅什先輩

臭泥の中に蓮花を生じるが如し

以前にネットで話題になった『おっさん=泥説』、すなわち、かわいい萌えキャラを描いているのはおっさんではあるが、きれいな蓮が泥の中から育つように、キャラがおっさんを通して顕現しているだけという説。

https://laza.mandarake.co.jp/comic004/img/339.png

laza.mandarake.co.jp

これが好きだったのですが、仏典に由来するという話を聞いて、さもありなんと思っておりました。ふと検索してみると、これが支那仏教初期の翻訳僧の鳩摩羅什(くまらじゅう)の言葉で、性的スキャンダルから自らの経典翻訳を「臭泥の中に蓮花を生じるが如し」と評した言葉に由来するようです。

臭い、汚い、泥のような羅什先輩

の道を外れ、

辱に塗れた、

戒僧

www.y-history.net

しかし、鳩摩羅什の像は宝石の国の金剛先生に雰囲気が似ていますね。 漫画原作の宝石の国は無茶苦茶になって終わってしまいましたがw

【寝言】夏至 至点

midsummer night

6月21日は夏至 summer solstice です。

夏至といえば毎年メンデルスゾーン真夏の夜の夢だったのですが、midsummer night は夏至の日の前の晩を指すようです。

AI と学ぶ真夏の夜の夢

\displaystyle{
\frac{(x+y)^2}{810} + \frac{(x-y)^2}{1000} = \pi
}

import numpy as np
import matplotlib.pyplot as plt

# Given values for a^2 and b^2
a2 = 810
b2 = 1000
pi_value = np.pi

# Compute the semi-major and semi-minor axes
a = np.sqrt(a2)
b = np.sqrt(b2)

# Parameters for the ellipse
theta = np.linspace(0, 2 * np.pi, 1000)
x = a * np.cos(theta)
y = b * np.sin(theta)

# Rotate the ellipse by -45 degrees
angle = np.radians(-45)
cos_angle = np.cos(angle)
sin_angle = np.sin(angle)

x_rotated = x * cos_angle - y * sin_angle
y_rotated = x * sin_angle + y * cos_angle

# Scale the ellipse to satisfy the equation = pi
scaling_factor = np.sqrt(pi_value)
x_scaled = x_rotated * scaling_factor
y_scaled = y_rotated * scaling_factor

# Plot the ellipse
plt.figure(figsize=(10, 6))
plt.fill(x_scaled, y_scaled, '#BC8F8F', label=r'$\frac{(x+y)^2}{810} + \frac{(x-y)^2}{1000} = \pi$')
plt.title('A Midsummer Night’s Dream')
plt.xlabel('x-axis')
plt.ylabel('y-axis')
plt.axhline(0, color='gray', lw=0.5)
plt.axvline(0, color='gray', lw=0.5)
plt.legend()
plt.grid(True)
plt.axis('equal')
plt.show()

AI と学ぶ四色問題

John Backus も取り組んだ四色問題ですが、ここでは男色問題・・・

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np

# 描画領域の設定
fig, ax = plt.subplots(figsize=(8, 6))

# 色の設定
color_circle = '#BC8F8F' # 円の色
color_top_left = '#A8C3C4'  # 左上の色
color_top_right = '#D3C9B3'  # 右上の色
color_bottom = '#3F3548'  # 下の色

# 頂点の座標を定義
triangle1 = [[-0.1, 1], [0.5, 1.0], [0.5, 0.5], [-0.1, 0.2]]
triangle2 = [[ 1.1, 1], [0.5, 1.0], [0.5, 0.5], [ 1.1, 0.2]]
triangle3 = [[-0.1, 0], [1.1, 0], [1.2, 0.2], [0.5, 0.5], [-0.1,0.2]]

# 三角形の描画
ax.add_patch(patches.Polygon(triangle1, color=color_top_left, zorder=0))
ax.add_patch(patches.Polygon(triangle2, color=color_top_right, zorder=0))
ax.add_patch(patches.Polygon(triangle3, color=color_bottom, zorder=0))

# 円の描画
circle = patches.Circle((0.5, 0.5), 0.3, color=color_circle, zorder=1)
ax.add_patch(circle)

# 軸の設定
ax.set_xlim(-0.1, 1.1)
ax.set_ylim(0, 1)
ax.set_aspect('equal')
ax.axis('off')

plt.show()

Apple Vision Pro

(Cyclops)

https://images.macrumors.com/t/eqNLvJ1HQWRdvKaRQnFfixx_s2I=/1600x0/article-new/2023/11/Apple-WWCD23-Vision-Pro-EyeSight-230605.jpg


www.youtube.com

メンデルスゾーン


www.youtube.com

この CD 好き。変な箱に入っているけど。