@@ -149,6 +149,12 @@ public bool DisableNative
149149 get => toolStripMenuItemDisableNative != null && toolStripMenuItemDisableNative . Checked ;
150150 set => toolStripMenuItemDisableNative . Checked = value ;
151151 }
152+ //260405Cl 追加
153+ public bool UseMKL
154+ {
155+ get => toolStripMenuItemUseMKL != null && toolStripMenuItemUseMKL . Checked ;
156+ set => toolStripMenuItemUseMKL . Checked = value ;
157+ }
152158 public static Languages Language => Thread . CurrentThread . CurrentUICulture . Name == "en" ? Languages . English : Languages . Japanese ;
153159 public double Phi { get => ( double ) numericUpDownEulerPhi . Value / 180.0 * Math . PI ; set => numericUpDownEulerPhi . Value = ( decimal ) ( value / Math . PI * 180.0 ) ; }
154160 public double Theta { get => ( double ) numericUpDownEulerTheta . Value / 180.0 * Math . PI ; set => numericUpDownEulerTheta . Value = ( decimal ) ( value / Math . PI * 180.0 ) ; }
@@ -243,9 +249,23 @@ public FormMain()
243249 return ;
244250
245251 //MainWindowの場所を読み込むため (InitializeComponentの後に読み込む)
252+ //260405Cl 起動時はUseMKLのCheckedChangedを抑制 (ip未初期化、ダウンロードダイアログ抑制のため)
253+ toolStripMenuItemUseMKL . CheckedChanged -= toolStripMenuItemUseMKL_CheckedChanged ;
246254 Registry ( Reg . Mode . Read ) ;
255+ toolStripMenuItemUseMKL . CheckedChanged += toolStripMenuItemUseMKL_CheckedChanged ;
247256
248-
257+ //260405Cl 起動時: UseMKLがチェックされていてDLLが存在する場合のみMKLを有効化
258+ if ( toolStripMenuItemUseMKL . Checked && MklFilesExist ( ) )
259+ {
260+ if ( MathNet . Numerics . Control . TryUseNativeMKL ( ) )
261+ BetheMethod . MklEnabled = true ;
262+ else
263+ toolStripMenuItemUseMKL . Checked = false ; //ロード失敗時はチェックを外す
264+ }
265+ else if ( toolStripMenuItemUseMKL . Checked && ! MklFilesExist ( ) )
266+ {
267+ toolStripMenuItemUseMKL . Checked = false ; //DLLがない場合はチェックを外す
268+ }
249269
250270 sw . Restart ( ) ;
251271
@@ -536,6 +556,8 @@ private void Registry(Reg.Mode mode)
536556 else if ( mode == Reg . Mode . Write )
537557 Reg . RW ( key , mode , this , nameof ( DisableNative ) , DisableNative ) ;
538558
559+ //260405Cl MKLライブラリを使うかどうか
560+ Reg . RW ( key , mode , this , nameof ( UseMKL ) , UseMKL ) ;
539561
540562 Reg . RW ( key , mode , commonDialog , nameof ( commonDialog . AutomaticallyClose ) , commonDialog . AutomaticallyClose ) ;
541563
@@ -1644,6 +1666,122 @@ private async void checkUpdatesToolStripMenuItem_Click(object sender, EventArgs
16441666
16451667 }
16461668
1669+ //260405Cl 追加: MKLライブラリのダウンロードと有効化
1670+ private static readonly string [ ] MklFileNames = [ "libMathNetNumericsMKL.dll" , "libiomp5md.dll" ] ;
1671+ private static string MklDirectory => AppDomain. CurrentDomain. BaseDirectory;
1672+
1673+ private static bool MklFilesExist ( ) => MklFileNames . All ( f => File . Exists ( Path . Combine ( MklDirectory , f ) ) ) ;
1674+
1675+ private async void toolStripMenuItemUseMKL_CheckedChanged ( object sender , EventArgs e )
1676+ {
1677+ if ( toolStripMenuItemUseMKL . Checked )
1678+ {
1679+ if ( ! MklFilesExist ( ) )
1680+ {
1681+ var result = MessageBox . Show (
1682+ "MKL library is not found.\r \n Download Intel MKL native library (~55 MB)?" ,
1683+ "Use MKL Library" , MessageBoxButtons . YesNo , MessageBoxIcon . Question ) ;
1684+
1685+ if ( result != DialogResult . Yes )
1686+ {
1687+ toolStripMenuItemUseMKL . CheckedChanged -= toolStripMenuItemUseMKL_CheckedChanged ;
1688+ toolStripMenuItemUseMKL . Checked = false ;
1689+ toolStripMenuItemUseMKL . CheckedChanged += toolStripMenuItemUseMKL_CheckedChanged ;
1690+ return ;
1691+ }
1692+
1693+ toolStripProgressBar . Visible = true ;
1694+ sw . Restart ( ) ;
1695+ try
1696+ {
1697+ var progress = new Progress < ( long Current , long Total , long ElapsedMilliseconds , string Message ) > ( p => ip . Report ( p ) ) ;
1698+ await DownloadAndExtractMklAsync ( progress ) ;
1699+ toolStripProgressBar . Visible = false ;
1700+ toolStripStatusLabel . Text = "MKL library downloaded successfully." ;
1701+ }
1702+ catch ( Exception ex )
1703+ {
1704+ toolStripProgressBar . Visible = false ;
1705+ toolStripMenuItemUseMKL . CheckedChanged -= toolStripMenuItemUseMKL_CheckedChanged ;
1706+ toolStripMenuItemUseMKL . Checked = false ;
1707+ toolStripMenuItemUseMKL . CheckedChanged += toolStripMenuItemUseMKL_CheckedChanged ;
1708+ MessageBox . Show ( $ "Failed to download MKL library.\r \n { ex . Message } ", "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
1709+ return ;
1710+ }
1711+ }
1712+
1713+ // MKLを有効化
1714+ if ( MathNet . Numerics . Control . TryUseNativeMKL ( ) )
1715+ {
1716+ BetheMethod . MklEnabled = true ;
1717+ toolStripStatusLabel . Text = "MKL library enabled." ;
1718+ }
1719+ else
1720+ {
1721+ toolStripMenuItemUseMKL . CheckedChanged -= toolStripMenuItemUseMKL_CheckedChanged ;
1722+ toolStripMenuItemUseMKL . Checked = false ;
1723+ toolStripMenuItemUseMKL . CheckedChanged += toolStripMenuItemUseMKL_CheckedChanged ;
1724+ MessageBox . Show ( "Failed to load MKL library." , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
1725+ }
1726+ }
1727+ else
1728+ {
1729+ // MKLを無効化 (managed実装にフォールバック)
1730+ MathNet . Numerics . Control . UseManaged ( ) ;
1731+ BetheMethod . MklEnabled = false ;
1732+ toolStripStatusLabel . Text = "MKL library disabled. Using managed implementation." ;
1733+ }
1734+ }
1735+
1736+ private static readonly System . Net . Http . HttpClient mklHttpClient = new ( ) ;
1737+
1738+ private async Task DownloadAndExtractMklAsync ( IProgress < ( long Current , long Total , long ElapsedMilliseconds , string Message ) > progress )
1739+ {
1740+ var nupkgUrl = "https://www.nuget.org/api/v2/package/MathNet.Numerics.MKL.Win-x64/3.0.0" ;
1741+ var tempFile = Path . Combine ( Path . GetTempPath ( ) , "MathNet.Numerics.MKL.Win-x64.3.0.0.nupkg" ) ;
1742+
1743+ try
1744+ {
1745+ // NuGetパッケージをダウンロード
1746+ using ( var response = await mklHttpClient . GetAsync ( new Uri ( nupkgUrl ) , System . Net . Http . HttpCompletionOption . ResponseHeadersRead ) )
1747+ {
1748+ response . EnsureSuccessStatusCode ( ) ;
1749+ var totalBytes = response . Content . Headers . ContentLength ?? - 1 ;
1750+ using var contentStream = await response . Content . ReadAsStreamAsync ( ) ;
1751+ using var fileStream = new FileStream ( tempFile , FileMode . Create , FileAccess . Write , FileShare . None , 8192 , true ) ;
1752+ var buffer = new byte [ 8192 ] ;
1753+ long bytesRead = 0 ;
1754+ int read ;
1755+ long counter = 0 ;
1756+ while ( ( read = await contentStream . ReadAsync ( buffer ) ) > 0 )
1757+ {
1758+ await fileStream . WriteAsync ( buffer . AsMemory ( 0 , read ) ) ;
1759+ bytesRead += read ;
1760+ if ( counter ++ % 10 == 0 )
1761+ progress ? . Report ( ProgramUpdates . ProgressMessage ( bytesRead , totalBytes , sw ) ) ;
1762+ }
1763+ }
1764+
1765+ // nupkgはZIPファイルなので展開してDLLを取り出す
1766+ using var archive = System . IO . Compression . ZipFile . OpenRead ( tempFile ) ;
1767+ foreach ( var fileName in MklFileNames )
1768+ {
1769+ var entry = archive . GetEntry ( $ "runtimes/win-x64/native/{ fileName } ") ;
1770+ if ( entry != null )
1771+ {
1772+ var destPath = Path . Combine ( MklDirectory , fileName ) ;
1773+ using var entryStream = entry . Open ( ) ;
1774+ using var destStream = new FileStream ( destPath , FileMode . Create , FileAccess . Write , FileShare . None ) ;
1775+ entryStream . CopyTo ( destStream ) ;
1776+ }
1777+ }
1778+ }
1779+ finally
1780+ {
1781+ if ( File . Exists ( tempFile ) )
1782+ File . Delete ( tempFile ) ;
1783+ }
1784+ }
16471785
16481786 /// <summary>進捗状況を更新</summary>
16491787 /// <param name="current"></param>
0 commit comments