ó
    Ë°æh"Æ  ã                   óÀ  • S r SSKrSSKrSSKrSSKrSSKrSSKrSSKJr  SSK	r	SSK
Jr  SSKJrJr  SSKJr  SSKJr  Sr/ S	Qr\R*                  R-                  S
S5        \R.                  S:”  a  \R0                  O\R2                  r\R.                  S:”  a  \R2                  O\R6                  r " S S\R:                  5      r \R>                  r  " S S\5      r# " S S\#5      r$ " S S\#5      r% " S S\#5      r& " S S\#5      r' " S S\#5      r(\$\%\'\(\&/r)\*" \+" S \) 5       5      5      r,\) V s/ s H  o RZ                  PM     sn r.\*" \+" S \) 5       5      5      r/\) V s/ s H   o R`                  S:X  d  M  U RZ                  PM"     sn r1\(Rd                  r3S r4S r5\" S S!9S" 5       r6\5" \*" \,5      \.S#9S$ 5       r7 " S% S&5      r8 " S' S(\8\5      r9\5" S)Ru                  S* \, 5       5      S)Ru                  \15      S)Ru                  \35      S+9 " S, S-\85      5       r; " S. S/5      r<S0 r=\>S1:X  a  \=" 5         gg! \! a    \RD                  r  GNf = fs  sn f s  sn f )2zÓthreadpoolctl

This module provides utilities to introspect native libraries that relies on
thread pools (notably BLAS and OpenMP implementations) and dynamically set the
maximal number of threads they can use.
é    N)Úfinal)Úfind_library)ÚABCÚabstractmethod)Ú	lru_cache)ÚContextDecoratorz3.6.0)Úthreadpool_limitsÚthreadpool_infoÚThreadpoolControllerÚLibControllerÚregisterÚKMP_DUPLICATE_LIB_OKÚTruel        c                   óX   • \ rS rSrS\4S\R                  4S\R                  4S\4/r	Sr
g)Ú_dl_phdr_infoé8   Ú	dlpi_addrÚ	dlpi_nameÚ	dlpi_phdrÚ
dlpi_phnum© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú_SYSTEM_UINTÚctypesÚc_char_pÚc_void_pÚ_SYSTEM_UINT_HALFÚ_fields_Ú__static_attributes__r   ó    ÚJ/home/mande/repo/quber/.venv/lib/python3.13/site-packages/threadpoolctl.pyr   r   8   s2   † à	�lÐ#Ø	�f—o‘oÐ&Ø	�f—o‘oÐ&Ø	Ð(Ð)ð	ƒHr#   r   c                   óŒ   • \ rS rSrSr\SSSS.S j5       rS rS r\	S 5       r
\S	 5       r\S
 5       r\S 5       rS rS rSrg)r   éH   a›  Abstract base class for the individual library controllers

A library controller must expose the following class attributes:
    - user_api : str
        Usually the name of the library or generic specification the library
        implements, e.g. "blas" is a specification with different implementations.
    - internal_api : str
        Usually the name of the library or concrete implementation of some
        specification, e.g. "openblas" is an implementation of the "blas"
        specification.
    - filename_prefixes : tuple
        Possible prefixes of the shared library's filename that allow to
        identify the library. e.g. "libopenblas" for libopenblas.so.

and implement the following methods: `get_num_threads`, `set_num_threads` and
`get_version`.

Threadpoolctl loops through all the loaded shared libraries and tries to match
the filename of each library with the `filename_prefixes`. If a match is found, a
controller is instantiated and a handler to the library is stored in the `dynlib`
attribute as a `ctypes.CDLL` object. It can be used to access the necessary symbols
of the shared library to implement the above methods.

The following information will be exposed in the info dictionary:
  - user_api : standardized API, if any, or a copy of internal_api.
  - internal_api : implementation-specific API.
  - num_threads : the current thread limit.
  - prefix : prefix of the shared library's filename.
  - filepath : path to the loaded shared library.
  - version : version of the library (if available).

In addition, each library controller may expose internal API specific entries. They
must be set as attributes in the `set_additional_attributes` method.
N©ÚfilepathÚprefixÚparentc                óè   • X0l         X l        Xl        [        R                  " U[
        S9U l        U R                  5       u  U l        U l	        U R                  5       U l        U R                  5         g)z0This is not meant to be overriden by subclasses.©ÚmodeN)r*   r)   r(   r   ÚCDLLÚ_RTLD_NOLOADÚdynlibÚ_find_affixesÚ_symbol_prefixÚ_symbol_suffixÚget_versionÚversionÚset_additional_attributes)Úselfr(   r)   r*   s       r$   Ú__init__ÚLibController.__init__l   sZ   € ð ŒØŒØ ŒÜ—k’k (´Ñ>ˆŒØ37×3EÑ3EÓ3GÑ0ˆÔ˜TÔ0Ø×'Ñ'Ó)ˆŒØ×&Ñ&Õ(r#   c                 óÄ   • SnU R                   U R                  U R                  S.[        U 5      R	                  5        VVs0 s H  u  p#X!;  d  M  X#_M     snnE$ s  snnf )ú&Return relevant info wrapped in a dict)r0   r*   r2   r3   )Úuser_apiÚinternal_apiÚnum_threads)r<   r=   r>   ÚvarsÚitems)r7   Úhidden_attrsÚkÚvs       r$   ÚinfoÚLibController.infow   sc   € àOˆàŸ™Ø ×-Ñ-Ø×+Ñ+ñ
ô !% T£
× 0Ñ 0Ô 2ÔLÒ 2™˜°aÑ6K‹tˆqŠtÑ 2ÒLð	
ð 	
ùó Ms   ÁAÁAc                 ó   • g)z>Set additional attributes meant to be exposed in the info dictNr   ©r7   s    r$   r6   Ú'LibController.set_additional_attributes�   ó   � r#   c                 ó"   • U R                  5       $ )zqExposes the current thread limit as a dynamic property

This is not meant to be used or overriden by subclasses.
)Úget_num_threadsrG   s    r$   r>   ÚLibController.num_threads„   s   € ð ×#Ñ#Ó%Ð%r#   c                 ó   • g)z5Return the maximum number of threads available to useNr   rG   s    r$   rK   ÚLibController.get_num_threadsŒ   rI   r#   c                 ó   • g)z(Set the maximum number of threads to useNr   )r7   r>   s     r$   Úset_num_threadsÚLibController.set_num_threads�   rI   r#   c                 ó   • g)z(Return the version of the shared libraryNr   rG   s    r$   r4   ÚLibController.get_version”   rI   r#   c                 ó   • g)z8Return the affixes for the symbols of the shared library)Ú rU   r   rG   s    r$   r1   ÚLibController._find_affixes˜   s   € àr#   c                 ód   • [        U R                  U R                   U U R                   3S5      $ )zBReturn the symbol of the shared library accounding for the affixesN)Úgetattrr0   r2   r3   )r7   Únames     r$   Ú_get_symbolÚLibController._get_symbolœ   s5   € äØ�K‰K˜D×/Ñ/Ð0°°°t×7JÑ7JÐ6KÐLÈdó
ð 	
r#   )r2   r3   r0   r(   r*   r)   r5   )r   r   r   r   Ú__doc__r   r8   rD   r6   Úpropertyr>   r   rK   rP   r4   r1   rZ   r"   r   r#   r$   r   r   H   sŠ   † ñ!ðF Ø#'°¸Tô )ó ð)ò
òMð ñ&ó ð&ð ñDó ðDð ñ7ó ð7ð ñ7ó ð7òõ
r#   r   c                   ó–   • \ rS rSrSrSrSrSrSrSr	\
" S \R                  " \\	5       5       5      rS	 rS
 rS rS rS rS rS rSrg)ÚOpenBLASControlleré£   zController class for OpenBLASÚblasÚopenblas)ÚlibopenblasÚlibblasÚlibscipy_openblas)rU   Úscipy_)rU   Ú64_Ú_64c              #   ó4   #   • U  H  u  pU S U 3v •  M     g7f)Úopenblas_get_num_threadsNr   )Ú.0r)   Úsuffixs      r$   Ú	<genexpr>ÚOpenBLASController.<genexpr>®   s%   é € ð âS‰NˆFð ˆ(Ð*¨6¨(Õ3ÚSùs   ‚c                 ó¶   • [         R                  " U R                  U R                  5       H*  u  p[	        U R
                  U SU 35      (       d  M'  X4s  $    g ©Nrj   )Ú	itertoolsÚproductÚ_symbol_prefixesÚ_symbol_suffixesÚhasattrr0   )r7   r)   rl   s      r$   r1   Ú OpenBLASController._find_affixes³   sQ   € Ü'×/Ò/Ø×!Ñ! 4×#8Ñ#8ö
‰NˆFô �t—{‘{ v hÐ.FÀvÀhÐ$O×PÓPØ�~Ò%ò	
r#   c                 óX   • U R                  5       U l        U R                  5       U l        g ©N©Ú_get_threading_layerÚthreading_layerÚ_get_architectureÚarchitecturerG   s    r$   r6   Ú,OpenBLASController.set_additional_attributesº   ó$   € Ø#×8Ñ8Ó:ˆÔØ ×2Ñ2Ó4ˆÕr#   c                 ó:   • U R                  S5      nUb  U" 5       $ g rp   ©rZ   )r7   Úget_num_threads_funcs     r$   rK   Ú"OpenBLASController.get_num_threads¾   s&   € Ø#×/Ñ/Ð0JÓKÐØÑ+Ù'Ó)Ð)Ør#   c                 ó<   • U R                  S5      nUb  U" U5      $ g )NÚopenblas_set_num_threadsr�   )r7   r>   Úset_num_threads_funcs      r$   rP   Ú"OpenBLASController.set_num_threadsÄ   s(   € Ø#×/Ñ/Ð0JÓKÐØÑ+Ù'¨Ó4Ð4Ør#   c                 ó¼   • U R                  S5      nUbH  [        R                  Ul        U" 5       R	                  5       nUS   S:X  a  US   R                  S5      $ g g )NÚopenblas_get_configr   s   OpenBLASé   úutf-8)rZ   r   r   ÚrestypeÚsplitÚdecode)r7   Úget_version_funcÚconfigs      r$   r4   ÚOpenBLASController.get_versionÊ   sa   € ð  ×+Ñ+Ð,AÓBÐØÑ'Ü'-§¡ÐÔ$Ù%Ó'×-Ñ-Ó/ˆFØ�a‰y˜KÓ'Ø˜a‘y×'Ñ'¨Ó0Ð0ØØr#   c                 óX   • U R                  S5      nUb  U" 5       nUS:X  a  gUS:X  a  ggg)z&Return the threading layer of OpenBLASÚopenblas_get_parallelé   ÚopenmprŠ   ÚpthreadsÚdisabledÚunknownr�   )r7   Úget_threading_layer_funcr{   s      r$   rz   Ú'OpenBLASController._get_threading_layerÖ   s>   € à#'×#3Ñ#3Ð4KÓ#LÐ Ø#Ñ/Ù6Ó8ˆOØ !Ó#ØØ  AÓ%Ø!ØØr#   c                 ó‚   • U R                  S5      nUb+  [        R                  Ul        U" 5       R	                  S5      $ g)z,Return the architecture detected by OpenBLASÚopenblas_get_corenameNr‹   )rZ   r   r   rŒ   rŽ   )r7   Úget_architecture_funcs     r$   r|   Ú$OpenBLASController._get_architectureâ   s>   € à $× 0Ñ 0Ð1HÓ IÐØ Ñ,Ü,2¯O©OÐ!Ô)Ù(Ó*×1Ñ1°'Ó:Ð:Ør#   ©r}   r{   N)r   r   r   r   r\   r<   r=   Úfilename_prefixesrs   rt   Útuplerq   rr   Úcheck_symbolsr1   r6   rK   rP   r4   rz   r|   r"   r   r#   r$   r_   r_   £   sl   † Ù'à€HØ€LØGÐà%ÐØ)Ðñ ñ à'×/Ò/Ð0@ÐBRÔSóó €Mò
&ò5òòò
ò
õr#   r_   c                   óL   • \ rS rSrSrSrSrSrSrS r	S r
S	 rS
 rS rS rSrg)ÚBLISControlleréë   zController class for BLISra   Úblis)Úlibblisrd   )Úbli_thread_get_num_threadsÚbli_thread_set_num_threadsÚbli_info_get_version_strÚbli_info_get_enable_openmpÚbli_info_get_enable_pthreadsÚbli_arch_query_idÚbli_arch_stringc                 óX   • U R                  5       U l        U R                  5       U l        g rx   ry   rG   s    r$   r6   Ú(BLISController.set_additional_attributesû   r   r#   c                 óT   • [        U R                  SS 5      nU" 5       nUS:X  a  S$ U$ )Nr¨   c                  ó   • g rx   r   r   r#   r$   Ú<lambda>Ú0BLISController.get_num_threads.<locals>.<lambda>   s   € Èdr#   éÿÿÿÿrŠ   ©rX   r0   ©r7   Úget_funcr>   s      r$   rK   ÚBLISController.get_num_threadsÿ   s0   € Ü˜4Ÿ;™;Ð(DÁlÓSˆÙ“jˆð   2Ó%ˆqÐ6¨;Ð6r#   c                 óB   • [        U R                  SS 5      nU" U5      $ )Nr©   c                 ó   • g rx   r   ©r>   s    r$   r³   Ú0BLISController.set_num_threads.<locals>.<lambda>  s   € È4r#   r¶   ©r7   r>   Úset_funcs      r$   rP   ÚBLISController.set_num_threads  s&   € ÜØ�K‰KÐ5Ñ7Oó
ˆñ ˜Ó$Ð$r#   c                 óŽ   • [        U R                  SS 5      nUc  g [        R                  Ul        U" 5       R                  S5      $ )Nrª   r‹   )rX   r0   r   r   rŒ   rŽ   )r7   Úget_version_s     r$   r4   ÚBLISController.get_version  s=   € Ü˜tŸ{™{Ð,FÈÓMˆØÑØä%Ÿ™ˆÔÙ‹~×$Ñ$ WÓ-Ð-r#   c                 ó�   • [        U R                  SS 5      " 5       (       a  g[        U R                  SS 5      " 5       (       a  gg)z"Return the threading layer of BLISr«   c                  ó   • g©NFr   r   r#   r$   r³   Ú5BLISController._get_threading_layer.<locals>.<lambda>  s   € Àer#   r•   r¬   c                  ó   • grÆ   r   r   r#   r$   r³   rÇ     s   € È%r#   r–   r—   r¶   rG   s    r$   rz   Ú#BLISController._get_threading_layer  s9   € ä�4—;‘;Ð <¹mÔL×NÑNØÜ�T—[‘[Ð"@Á-ÔP×RÑRØØr#   c                 óø   • [        U R                  SS5      n[        U R                  SS5      nUb  Uc  g[        R                  Ul        [        R
                  Ul        U" U" 5       5      R                  S5      $ )z(Return the architecture detected by BLISr­   Nr®   r‹   )rX   r0   r   Úc_intrŒ   r   rŽ   )r7   r­   r®   s      r$   r|   Ú BLISController._get_architecture  sl   € ä# D§K¡KÐ1DÀdÓKÐÜ! $§+¡+Ð/@À$ÓGˆØÑ$¨Ñ(?Øô %+§L¡LÐÔ!Ü"(§/¡/ˆÔÙÑ0Ó2Ó3×:Ñ:¸7ÓCÐCr#   rŸ   N)r   r   r   r   r\   r<   r=   r    r¢   r6   rK   rP   r4   rz   r|   r"   r   r#   r$   r¤   r¤   ë   s;   † Ù#à€HØ€LØ.Ðð€Mò5ò7ò%ò.òõDr#   r¤   c                   óŠ   ^ • \ rS rSrSrSrSrSrSr\	S 5       r
\	S 5       rU 4S	 jrS
 rS rS rS rSS jrS rS rSrU =r$ )ÚFlexiBLASControlleri*  zController class for FlexiBLASra   Ú	flexiblas)Úlibflexiblas)Úflexiblas_get_num_threadsÚflexiblas_set_num_threadsÚflexiblas_get_versionÚflexiblas_listÚflexiblas_list_loadedÚflexiblas_current_backendc                 ó    • U R                  SS9$ )NT©Úloaded)Ú_get_backend_listrG   s    r$   Úloaded_backendsÚ#FlexiBLASController.loaded_backends9  s   € à×%Ñ%¨TÐ%Ð2Ð2r#   c                 ó"   • U R                  5       $ rx   )Ú_get_current_backendrG   s    r$   Úcurrent_backendÚ#FlexiBLASController.current_backend=  s   € à×(Ñ(Ó*Ð*r#   c                 ó`   >• [         TU ]  5       nU R                  US'   U R                  US'   U$ )r;   rÛ   rß   )ÚsuperrD   rÛ   rß   )r7   Úexposed_attrsÚ	__class__s     €r$   rD   ÚFlexiBLASController.infoA  s8   ø€ ô ™™›ˆØ+/×+?Ñ+?ˆÐ'Ñ(Ø+/×+?Ñ+?ˆÐ'Ñ(àÐr#   c                 ó,   • U R                  SS9U l        g )NFrØ   )rÚ   Úavailable_backendsrG   s    r$   r6   Ú-FlexiBLASController.set_additional_attributesK  s   € Ø"&×"8Ñ"8ÀÐ"8Ð"FˆÕr#   c                 óT   • [        U R                  SS 5      nU" 5       nUS:X  a  S$ U$ )NrÑ   c                  ó   • g rx   r   r   r#   r$   r³   Ú5FlexiBLASController.get_num_threads.<locals>.<lambda>O  s   € ÈTr#   rµ   rŠ   r¶   r·   s      r$   rK   Ú#FlexiBLASController.get_num_threadsN  s0   € Ü˜4Ÿ;™;Ð(CÁ\ÓRˆÙ“jˆð   2Ó%ˆqÐ6¨;Ð6r#   c                 óB   • [        U R                  SS 5      nU" U5      $ )NrÒ   c                 ó   • g rx   r   r¼   s    r$   r³   Ú5FlexiBLASController.set_num_threads.<locals>.<lambda>W  s   € È$r#   r¶   r¾   s      r$   rP   Ú#FlexiBLASController.set_num_threadsU  s&   € ÜØ�K‰KÐ4Ñ6Nó
ˆñ ˜Ó$Ð$r#   c                 ó’  • [        U R                  SS 5      nUc  g [        R                  " 5       n[        R                  " 5       n[        R                  " 5       nU" [        R                  " U5      [        R                  " U5      [        R                  " U5      5        UR
                   SUR
                   SUR
                   3$ )NrÓ   Ú.)rX   r0   r   rË   ÚbyrefÚvalue)r7   rÂ   ÚmajorÚminorÚpatchs        r$   r4   ÚFlexiBLASController.get_version[  s‰   € Ü˜tŸ{™{Ð,CÀTÓJˆØÑØä—’“ˆÜ—’“ˆÜ—’“ˆÙ”V—\’\ %Ó(¬&¯,ª,°uÓ*=¼v¿|º|ÈEÓ?RÔSØ—+‘+�˜a §¡˜}¨A¨e¯k©k¨]Ð;Ð;r#   c                 ój  • SU(       a  SOS 3n[        U R                  US5      nUc  gU" SSS5      n/ n[        U5       Hn  n[        R                  " S5      nU" USU5        UR
                  R                  S5      S:w  d  MD  UR                  UR
                  R                  S5      5        Mp     U$ )	zÒReturn the list of available backends for FlexiBLAS.

If loaded is False, return the list of available backends from the FlexiBLAS
configuration. If loaded is True, return the list of actually loaded backends.
rÔ   Ú_loadedrU   Nr   é   r‹   Ú__FALLBACK__)rX   r0   Úranger   Úcreate_string_bufferrô   rŽ   Úappend)r7   rÙ   Ú	func_nameÚget_backend_list_Ú
n_backendsÚbackendsÚiÚbackend_names           r$   rÚ   Ú%FlexiBLASController._get_backend_listf  s®   € ð %¶&¡Y¸bÐ$AÐBˆ	Ü# D§K¡K°¸DÓAÐØÑ$Øá& t¨Q°Ó2ˆ
àˆÜ�zÖ"ˆAÜ!×6Ò6°tÓ<ˆLÙ˜l¨D°!Ô4Ø×!Ñ!×(Ñ(¨Ó1°^ÕCð —‘ × 2Ñ 2× 9Ñ 9¸'Ó BÖCñ #ð ˆr#   c                 óÔ   • [        U R                  SS5      nUc  g[        R                  " S5      nU" U[        R                  " U5      5        UR
                  R                  S5      $ )zReturn the backend of FlexiBLASrÖ   Nrû   r‹   )rX   r0   r   rþ   Úsizeofrô   rŽ   )r7   Úget_backend_Úbackends      r$   rÞ   Ú(FlexiBLASController._get_current_backend}  sV   € ä˜tŸ{™{Ð,GÈÓNˆØÑØä×-Ò-¨dÓ3ˆÙ�WœfŸmšm¨GÓ4Ô5Ø�}‰}×#Ñ# GÓ,Ð,r#   c                 óþ  • XR                   ;  a�  XR                  ;   a  [        U R                  SS 5      nO[        U R                  SS 5      nU" [	        U5      R                  S5      5      nUS:X  a  [        SU< SU R                   S	35      eU R                  R                  5         [        U R                  S
S 5      nU R                   R                  U5      nU" U5      nUS:X  a  [        SU< S35      eg)zÔSwitch the backend of FlexiBLAS

Parameters
----------
backend : str
    The name or the path to the shared library of the backend to switch to. If
    the backend is not already loaded, it will be loaded first.
Úflexiblas_load_backendc                 ó   • g©Nrµ   r   ©Ú_s    r$   r³   Ú4FlexiBLASController.switch_backend.<locals>.<lambda>’  s   € ÐUWr#   Úflexiblas_load_backend_libraryc                 ó   • gr  r   r  s    r$   r³   r  •  s   € ÈRr#   r‹   rµ   zFailed to load backend zS. It must either be the name of a backend available in the FlexiBLAS configuration z' or the path to a valid shared library.Úflexiblas_switchc                 ó   • gr  r   r  s    r$   r³   r  £  s   € Èr#   zFailed to switch to backend rò   N)
rÛ   rç   rX   r0   ÚstrÚencodeÚRuntimeErrorr*   Ú_load_librariesÚindex)r7   r
  Ú	load_funcÚresÚswitch_funcÚidxs         r$   Úswitch_backendÚ"FlexiBLASController.switch_backend‡  sü   € ð ×.Ñ.Ó.Ø×1Ñ1Ó1Ü# D§K¡KÐ1IÉ<ÓX‘	ä#Ø—K‘KÐ!AÁ<ó�	ñ œC ›L×/Ñ/°Ó8Ó9ˆCØ�b‹yÜ"Ø-¨g©[ð 9Kà×.Ñ.Ð/Ð/VðXóð ð �K‰K×'Ñ'Ô)ä˜dŸk™kÐ+=¹|ÓLˆØ×"Ñ"×(Ñ(¨Ó1ˆÙ˜#ÓˆØ�"‹9ÜÐ!=¸g¹[ÈÐJÓKÐKð r#   )rç   )F)r   r   r   r   r\   r<   r=   r    r¢   r]   rÛ   rß   rD   r6   rK   rP   r4   rÚ   rÞ   r   r"   Ú__classcell__©rä   s   @r$   rÎ   rÎ   *  su   ø† Ù(à€HØ€LØ)Ðð€Mð ñ3ó ð3ð ñ+ó ð+õòGò7ò%ò	<ôò.-÷ Lð  Lr#   rÎ   c                   óF   • \ rS rSrSrSrSrSrSrS r	S r
S	 rS
 rS rSrg)ÚMKLControlleriª  zController class for MKLra   Úmkl)Ú	libmkl_rtÚmkl_rtrd   )ÚMKL_Get_Max_ThreadsÚMKL_Set_Num_ThreadsÚMKL_Get_Version_StringÚMKL_Set_Threading_Layerc                 ó.   • U R                  5       U l        g rx   )rz   r{   rG   s    r$   r6   Ú'MKLController.set_additional_attributes·  s   € Ø#×8Ñ8Ó:ˆÕr#   c                 ó@   • [        U R                  SS 5      nU" 5       $ )Nr)  c                  ó   • g rx   r   r   r#   r$   r³   Ú/MKLController.get_num_threads.<locals>.<lambda>»  ó   € Àtr#   r¶   ©r7   r¸   s     r$   rK   ÚMKLController.get_num_threadsº  ó   € Ü˜4Ÿ;™;Ð(=¹|ÓLˆÙ‹zÐr#   c                 óB   • [        U R                  SS 5      nU" U5      $ )Nr*  c                 ó   • g rx   r   r¼   s    r$   r³   Ú/MKLController.set_num_threads.<locals>.<lambda>¿  ó   € ÐSWr#   r¶   r¾   s      r$   rP   ÚMKLController.set_num_threads¾  ó!   € Ü˜4Ÿ;™;Ð(=Ñ?WÓXˆÙ˜Ó$Ð$r#   c                 óN  • [        U R                  S5      (       d  g [        R                  " S5      nU R                  R	                  US5        UR
                  R                  S5      n[        R                  " SU5      nUb  UR                  5       S   nUR                  5       $ )Nr+  éÈ   r‹   zVersion ([^ ]+) r   )ru   r0   r   rþ   r+  rô   rŽ   ÚreÚsearchÚgroupsÚstrip)r7   r  r5   Úgroups       r$   r4   ÚMKLController.get_versionÂ  s‚   € Ü�t—{‘{Ð$<×=Ñ=Øä×)Ò)¨#Ó.ˆØ�‰×*Ñ*¨3°Ô4à—)‘)×"Ñ" 7Ó+ˆÜ—	’	Ð-¨wÓ7ˆØÑØ—l‘l“n QÑ'ˆGØ�}‰}‹Ðr#   c                 óX   • [        U R                  SS 5      nSSSSSSS	.nX!" S
5         $ )z!Return the threading layer of MKLr,  c                 ó   • gr  r   )Úlayers    r$   r³   Ú4MKLController._get_threading_layer.<locals>.<lambda>Õ  s   € À"r#   ÚintelÚ
sequentialÚpgiÚgnuÚtbbznot specified)r   rŠ   r”   é   é   rµ   rµ   r¶   )r7   Úset_threading_layerÚ	layer_maps      r$   rz   Ú"MKLController._get_threading_layerÏ  sJ   € ô
 &Ø�K‰KÐ2Ñ4Dó
Ðð ØØØØØñ
ˆ	ð Ð,¨RÓ0Ñ1Ð1r#   )r{   N)r   r   r   r   r\   r<   r=   r    r¢   r6   rK   rP   r4   rz   r"   r   r#   r$   r%  r%  ª  s5   † Ù"à€HØ€LØ:Ðð€Mò;òò%òõ2r#   r%  c                   ó:   • \ rS rSrSrSrSrSrSrS r	S r
S rS	rg
)ÚOpenMPControlleriâ  zController class for OpenMPr•   )ÚlibiompÚlibgompÚlibompÚvcomp)Úomp_get_max_threadsÚomp_get_num_threadsc                 ó@   • [        U R                  SS 5      nU" 5       $ )NrX  c                  ó   • g rx   r   r   r#   r$   r³   Ú2OpenMPController.get_num_threads.<locals>.<lambda>î  r2  r#   r¶   r3  s     r$   rK   Ú OpenMPController.get_num_threadsí  r5  r#   c                 óB   • [        U R                  SS 5      nU" U5      $ )NÚomp_set_num_threadsc                 ó   • g rx   r   r¼   s    r$   r³   Ú2OpenMPController.set_num_threads.<locals>.<lambda>ò  r9  r#   r¶   r¾   s      r$   rP   Ú OpenMPController.set_num_threadsñ  r;  r#   c                 ó   • g rx   r   rG   s    r$   r4   ÚOpenMPController.get_versionõ  s   € àr#   r   N)r   r   r   r   r\   r<   r=   r    r¢   rK   rP   r4   r"   r   r#   r$   rS  rS  â  s+   † Ù%à€HØ€LØAÐð€Mò
ò%õr#   rS  c              #   ó8   #   • U  H  oR                   v •  M     g 7frx   )r<   ©rk   Úlibs     r$   rm   rm     s   é € ÐCÒ2B¨3Ÿ,ž,Ò2Bùó   ‚c              #   óJ   #   • U  H  oR                     H  o"v •  M     M     g 7frx   )r    )rk   rg  r)   s      r$   rm   rm     s   é € ÐOÒ*�3×9NÕ9N¨vŒÑ9N‰Ò*ùs   ‚!#ra   c                 óè   • [         R                  U 5        [        R                  U R                  5        [        R                  U R
                  5        [        R                  U R                  5        g)zRegister a new controllerN)	Ú_ALL_CONTROLLERSrÿ   Ú_ALL_USER_APISr<   Ú_ALL_INTERNAL_APISr=   Ú_ALL_PREFIXESÚextendr    )Ú
controllers    r$   r   r     sL   € ä×Ñ˜JÔ'Ü×Ñ˜*×-Ñ-Ô.Ü×Ñ˜j×5Ñ5Ô6Ü×Ñ˜×5Ñ5Õ6r#   c                  ó   ^ ^• U U4S jnU$ )Nc                 ód   >• U R                   b!  U R                   R                  " T0 TD6U l         U $ rx   )r\   Úformat)ÚoÚargsÚkwargss    €€r$   Ú	decoratorÚ$_format_docstring.<locals>.decorator  s-   ø€ Ø�9‰9Ñ ØŸ	™	×(Ò(¨$Ð9°&Ñ9ˆAŒIØˆr#   r   )ru  rv  rw  s   `` r$   Ú_format_docstringry    s   ù€ öð
 Ðr#   i'  )Úmaxsizec                 ó@   • [         R                  R                  U 5      $ )zCSmall caching wrapper around os.path.realpath to limit system calls)ÚosÚpathÚrealpath©r(   s    r$   Ú	_realpathr€  !  s   € ô �7‰7×Ñ˜HÓ%Ð%r#   )Ú	USER_APISÚINTERNAL_APISc                  ó2   • [        5       R                  5       $ )ad  Return the maximal number of threads for each detected library.

Return a list with all the supported libraries that have been found. Each
library is represented by a dict with the following information:

  - "user_api" : user API. Possible values are {USER_APIS}.
  - "internal_api": internal API. Possible values are {INTERNAL_APIS}.
  - "prefix" : filename prefix of the specific implementation.
  - "filepath": path to the loaded library.
  - "version": version of the library (if available).
  - "num_threads": the current thread limit.

In addition, each library may contain internal_api specific entries.
)r   rD   r   r#   r$   r
   r
   '  s   € ô   Ó!×&Ñ&Ó(Ð(r#   c                   ój   • \ rS rSrSrSSS.S jrS rS r\SSS.S j5       r	S	 r
\
rS
 rS rS rSrg)Ú_ThreadpoolLimiteri:  aŒ  The guts of ThreadpoolController.limit

Refer to the docstring of ThreadpoolController.limit for more details.

It will only act on the library controllers held by the provided `controller`.
Using the default constructor sets the limits right away such that it can be used as
a callable. Setting the limits can be delayed by using the `wrap` class method such
that it can be used as a decorator.
N©Úlimitsr<   c                ó¶   • Xl         U R                  X#5      u  U l        U l        U l        U R                   R                  5       U l        U R                  5         g rx   )Ú_controllerÚ_check_paramsÚ_limitsÚ	_user_apiÚ	_prefixesrD   Ú_original_infoÚ_set_threadpool_limits©r7   rp  r‡  r<   s       r$   r8   Ú_ThreadpoolLimiter.__init__E  sM   € Ø%ÔØ7;×7IÑ7IØó8
Ñ4ˆŒ�d”n d¤nð #×.Ñ.×3Ñ3Ó5ˆÔØ×#Ñ#Õ%r#   c                 ó   • U $ rx   r   rG   s    r$   Ú	__enter__Ú_ThreadpoolLimiter.__enter__M  s   € Øˆr#   c                 ó$   • U R                  5         g rx   )Úrestore_original_limits)r7   Útyperô   Ú	tracebacks       r$   Ú__exit__Ú_ThreadpoolLimiter.__exit__P  s   € Ø×$Ñ$Õ&r#   c                ó   • [        XUS9$ )z@Return an instance of this class that can be used as a decorator)rp  r‡  r<   )Ú_ThreadpoolLimiterDecorator)Úclsrp  r‡  r<   s       r$   ÚwrapÚ_ThreadpoolLimiter.wrapS  s   € ô +Ø!¸8ñ
ð 	
r#   c                 ó’   • [        U R                  R                  U R                  5       H  u  pUR	                  US   5        M     g)z,Set the limits back to their original valuesr>   N)Úzipr‰  Úlib_controllersrŽ  rP   )r7   Úlib_controllerÚoriginal_infos      r$   r–  Ú*_ThreadpoolLimiter.restore_original_limitsZ  s@   € ä-0Ø×Ñ×,Ñ,¨d×.AÑ.Aö.
Ñ)ˆNð ×*Ñ*¨=¸Ñ+GÖHò.
r#   c                 ó¢  • 0 n/ nU R                    Hƒ  nU R                   Vs/ s H  nUS   U:X  d  M  US   PM     nn[        U5      n[        U5      nUS:X  a  UR	                  5       nO%US:X  a  SnO[        U5      nUR                  U5        XqU'   M…     U(       a+  [        R                  " SSR                  U5      -   S-   5        U$ s  snf )	zeOriginal num_threads from before calling threadpool_limits

Return a dict `{user_api: num_threads}`.
r<   r>   rŠ   r   Nz1Multiple value possible for following user apis: ú, z. Returning the minimum.)
rŒ  rŽ  ÚsetÚlenÚpopÚminrÿ   ÚwarningsÚwarnÚjoin)r7   r>   Úwarning_apisr<   Úlib_infor‡  Ún_limitsÚlimits           r$   Úget_original_num_threadsÚ+_ThreadpoolLimiter.get_original_num_threadsd  sã   € ð
 ˆØˆàŸœˆHð !%× 3Ò 3óâ 3�HØ˜JÑ'¨8Ñ3ó (�˜Ô'Ù 3ð ð ô
 ˜“[ˆFÜ˜6“{ˆHà˜1‹}ØŸ
™
›‘Ø˜Q“Ø‘ä˜F›�Ø×#Ñ# HÔ-à$)˜Ó!ñ# 'ö& Ü�MŠMØCØ—)‘)˜LÓ)ñ*à,ñ-ôð Ðùò3s
   ¢C³	Cc                 ó:  • [        U[        5      (       a1  US:X  a+  U R                  R                  5       R	                  5       u  nnUb  [        U[
        5      (       aF  Uc  [        nO$U[        ;   a  U/nO[        S[         SU S35      eUb  U Vs0 s H  o3U_M     nn/ nOÛ[        U[        5      (       a  U Vs0 s H  oUS   US   _M     nnOF[        U[        5      (       a1  UR                   Vs0 s H  nUR                  UR                  _M     nn[        U[        5      (       d  [        S[        U5       S35      eU Vs/ s H  ow[         ;   d  M  UPM     nnU Vs/ s H  o3[        ;   d  M  UPM     nnXU4$ s  snf s  snf s  snf s  snf s  snf )	zCSuitable values for the _limits, _user_api and _prefixes attributesÚsequential_blas_under_openmpzuser_api must be either in z or None. Got z	 instead.r)   r>   zUlimits must either be an int, a list, a dict, or 'sequential_blas_under_openmp'. Got z instead)Ú
isinstancer  r‰  Ú,_get_params_for_sequential_blas_under_openmpÚvaluesÚintrl  Ú
ValueErrorÚlistr   r¢  r)   r>   ÚdictÚ	TypeErrorr—  rn  )r7   r‡  r<   ÚapiÚprefixesr°  r£  r)   s           r$   rŠ  Ú _ThreadpoolLimiter._check_paramsˆ  sÃ  € ô �fœc×"Ñ" vÐ1OÓ'Oð × Ñ ×MÑMÓO×VÑVÓXñØØð ‰>œZ¨´×4Ñ4ØÑÜ)‘Øœ^Ó+Ø$˜:‘ä Ø1´.Ð1AÀØ�j 	ð+óð ð
 Ñ!Ù19Ó:²¨#˜vš+±�Ð:Ø‰Hä˜&¤$×'Ñ'ñ QWóÚPVÀH˜XÑ&¨°Ñ(?Ò?ÑPVð ð �ô ˜FÔ$8×9Ñ9ð
 +1×*@Ò*@óâ*@˜ð #×)Ñ)¨>×+EÑ+EÒEÙ*@ð ð ô
 ˜f¤d×+Ñ+Üð;Ü;?À»<¸.ÈðRóð ñ .4ÓOªV 6ÄÑ7NŸ©VˆHÐOÙ'-ÓG¢v ¼Ñ1FŸ¡vˆHÐGà Ð)Ð)ùò9 ;ùòùòùò PùÚGs*   ÂFÂ>F	Ã6!FÅ
FÅFÅ'FÅ8Fc                 óZ  • U R                   c  gU R                  R                   Hƒ  nUR                  U R                   ;   a  U R                   UR                     nO6UR                  U R                   ;   a  U R                   UR                     nOMm  Uc  Mr  UR                  U5        M…     g)z´Change the maximal number of threads in selected thread pools.

Return a list with all the supported libraries that have been found
matching `self._prefixes` and `self._user_api`.
N)r‹  r‰  r¢  r)   r<   rP   )r7   r£  r>   s      r$   r�  Ú)_ThreadpoolLimiter._set_threadpool_limits»  sŒ   € ð �<‰<ÑØà"×.Ñ.×>Ô>ˆNð ×$Ñ$¨¯©Ó4Ø"Ÿl™l¨>×+@Ñ+@ÑA‘Ø×(Ñ(¨D¯L©LÓ8Ø"Ÿl™l¨>×+BÑ+BÑC‘áàÓ&Ø×.Ñ.¨{Ö;ò ?r#   ©r‰  r‹  rŽ  r�  rŒ  )r   r   r   r   r\   r8   r“  r™  Úclassmethodrž  r–  Ú
unregisterr³  rŠ  r�  r"   r   r#   r$   r…  r…  :  sT   † ñð .2¸Dõ &òò'ð Ø(,°tô 
ó ð
òIð )€Jò"òH1*õf<r#   r…  c                   ó.   • \ rS rSrSrSSS.S jrS rSrg)rœ  iÓ  z8Same as _ThreadpoolLimiter but to be used as a decoratorNr†  c                óX   • U R                  X#5      u  U l        U l        U l        Xl        g rx   )rŠ  r‹  rŒ  r�  r‰  r�  s       r$   r8   Ú$_ThreadpoolLimiterDecorator.__init__Ö  s*   € Ø7;×7IÑ7IØó8
Ñ4ˆŒ�d”n d¤nð &Õr#   c                 ód   • U R                   R                  5       U l        U R                  5         U $ rx   )r‰  rD   rŽ  r�  rG   s    r$   r“  Ú%_ThreadpoolLimiterDecorator.__enter__Ü  s,   € ð #×.Ñ.×3Ñ3Ó5ˆÔØ×#Ñ#Ô%Øˆr#   rÄ  )r   r   r   r   r\   r8   r“  r"   r   r#   r$   rœ  rœ  Ó  s   † ÙBà-1¸Dõ &õr#   rœ  r§  c              #   ó.   #   • U  H  nS U S 3v •  M     g7f)Ú"Nr   ©rk   r¿  s     r$   rm   rm   æ  s   é € Ð=ªn s˜!˜C˜5 �
ªnùs   ‚©r�  Ú	BLAS_LIBSÚOPENMP_LIBSc                   óJ   ^ • \ rS rSrSrSU 4S jjr\SU 4S jj5       rSrU =r	$ )r	   iå  aç  Change the maximal number of threads that can be used in thread pools.

This object can be used either as a callable (the construction of this object
limits the number of threads), as a context manager in a `with` block to
automatically restore the original state of the controlled libraries when exiting
the block, or as a decorator through its `wrap` method.

Set the maximal number of threads that can be used in thread pools used in
the supported libraries to `limit`. This function works for libraries that
are already loaded in the interpreter and can be changed dynamically.

This effect is global and impacts the whole Python process. There is no thread level
isolation as these libraries do not offer thread-local APIs to configure the number
of threads to use in nested parallel calls.

Parameters
----------
limits : int, dict, 'sequential_blas_under_openmp' or None (default=None)
    The maximal number of threads that can be used in thread pools

    - If int, sets the maximum number of threads to `limits` for each
      library selected by `user_api`.

    - If it is a dictionary `{{key: max_threads}}`, this function sets a
      custom maximum number of threads for each `key` which can be either a
      `user_api` or a `prefix` for a specific library.

    - If 'sequential_blas_under_openmp', it will chose the appropriate `limits`
      and `user_api` parameters for the specific use case of sequential BLAS
      calls within an OpenMP parallel region. The `user_api` parameter is
      ignored.

    - If None, this function does not do anything.

user_api : {USER_APIS} or None (default=None)
    APIs of libraries to limit. Used only if `limits` is an int.

    - If "blas", it will only limit BLAS supported libraries ({BLAS_LIBS}).

    - If "openmp", it will only limit OpenMP supported libraries
      ({OPENMP_LIBS}). Note that it can affect the number of threads used
      by the BLAS libraries if they rely on OpenMP.

    - If None, this function will apply to all supported libraries.
c                 ó2   >• [         TU ]  [        5       XS9  g ©Nr†  )râ   r8   r   )r7   r‡  r<   rä   s      €r$   r8   Úthreadpool_limits.__init__  s   ø€ Ü‰ÑÔ-Ó/¸ÐÒRr#   c                 ó0   >• [         TU ]  [        5       XS9$ rÔ  )râ   rž  r   )r�  r‡  r<   rä   s      €r$   rž  Úthreadpool_limits.wrap  s   ø€ ä‰w‰|Ô0Ó2¸6ˆ|ÐUÐUr#   r   )NN)
r   r   r   r   r\   r8   rÅ  rž  r"   r"  r#  s   @r$   r	   r	   å  s%   ø† ñ,÷\Sð öVó öVr#   r	   c                   óÀ  • \ rS rSrSr\" 5       rS r\S 5       r	S r
S rS r\" SR                  S	 \ 5       5      SR                  \5      SR                  \5      S
9SSS.S j5       r\" SR                  S \ 5       5      SR                  \5      SR                  \5      S
9SSS.S j5       rS rS rS rS rS rS rS rS rS r\S 5       r\S 5       rSrg)r   i!  z×Collection of LibController objects for all loaded supported libraries

Attributes
----------
lib_controllers : list of `LibController` objects
    The list of library controllers of all loaded supported libraries.
c                 óR   • / U l         U R                  5         U R                  5         g rx   )r¢  r  Ú_warn_if_incompatible_openmprG   s    r$   r8   ÚThreadpoolController.__init__0  s"   € Ø!ˆÔØ×ÑÔØ×)Ñ)Õ+r#   c                 ó4   • U R                  U 5      nXl        U$ rx   )Ú__new__r¢  )r�  r¢  Únew_controllers      r$   Ú_from_controllersÚ&ThreadpoolController._from_controllers5  s   € àŸ™ SÓ)ˆØ)8Ô&ØÐr#   c                 ó`   • U R                    Vs/ s H  oR                  5       PM     sn$ s  snf )z.Return lib_controllers info as a list of dicts)r¢  rD   )r7   r£  s     r$   rD   ÚThreadpoolController.info;  s)   € à<@×<PÒ<PÓQÒ<P¨.×#Ñ#Ö%Ñ<PÑQÐQùÒQs   �+c                 ó0  ^• UR                  5        H!  u  p#[        U[        5      (       d  U/OUX'   M#     U R                   V^s/ s H/  m[	        U4S jUR                  5        5       5      (       d  M-  TPM1     nn[
        R                  U5      $ s  snf )aö  Return a ThreadpoolController containing a subset of its current
library controllers

It will select all libraries matching at least one pair (key, value) from kwargs
where key is an entry of the library info dict (like "user_api", "internal_api",
"prefix", ...) and value is the value or a list of acceptable values for that
entry.

For instance, `ThreadpoolController().select(internal_api=["blis", "openblas"])`
will select all library controllers whose internal_api is either "blis" or
"openblas".
c              3   óH   >#   • U  H  u  p[        TUS 5      U;   v •  M     g 7frx   )rX   )rk   ÚkeyÚvalsr£  s      €r$   rm   Ú.ThreadpoolController.select.<locals>.<genexpr>R  s(   øé € ð â!/‘I�Cô ˜¨¨TÓ2°dÖ:Ú!/ùs   ƒ")r@   r·  r¼  r¢  Úanyr   rß  )r7   rv  rå  ræ  r£  r¢  s       ` r$   ÚselectÚThreadpoolController.select?  s‰   ø€ ð  Ÿ™ž‰IˆCÜ(2°4¼×(>Ñ(>˜4™&ÀDˆF‹Kñ (ð
 #'×"6Ò"6ô
â"6�Üô à!'§¡¤ó÷ ÷ Ù"6ð 	ð 
ô $×5Ñ5°oÓFÐFùò
s   Á,BÁ6Bc                 óT   • U R                  SSS9R                  (       a  SSS.$ SSS.$ )zµReturn appropriate params to use for a sequential BLAS call in an OpenMP loop

This function takes into account the unexpected behavior of OpenBLAS with the
OpenMP threading layer.
rb   r•   )r=   r{   Nr†  rŠ   ra   )ré  r¢  rG   s    r$   r¸  ÚAThreadpoolController._get_params_for_sequential_blas_under_openmpZ  s<   € ð �;‰;Ø#°Xð ð 
ç
‰/õð #°Ñ5Ð5Ø¨Ñ0Ð0r#   r§  c              #   óD   #   • U  H  nS R                  U5      v •  M     g7f©z"{}"N©rs  rÎ  s     r$   rm   ÚThreadpoolController.<genexpr>g  ó   é € ÐIº.°3˜FŸM™M¨#×.Ð.º.ùó   ‚ rÏ  Nr†  c                ó   • [        XUS9$ )a×  Change the maximal number of threads that can be used in thread pools.

This function returns an object that can be used either as a callable (the
construction of this object limits the number of threads) or as a context
manager, in a `with` block to automatically restore the original state of the
controlled libraries when exiting the block.

Set the maximal number of threads that can be used in thread pools used in
the supported libraries to `limits`. This function works for libraries that
are already loaded in the interpreter and can be changed dynamically.

This effect is global and impacts the whole Python process. There is no thread
level isolation as these libraries do not offer thread-local APIs to configure
the number of threads to use in nested parallel calls.

Parameters
----------
limits : int, dict, 'sequential_blas_under_openmp' or None (default=None)
    The maximal number of threads that can be used in thread pools

    - If int, sets the maximum number of threads to `limits` for each
      library selected by `user_api`.

    - If it is a dictionary `{{key: max_threads}}`, this function sets a
      custom maximum number of threads for each `key` which can be either a
      `user_api` or a `prefix` for a specific library.

    - If 'sequential_blas_under_openmp', it will chose the appropriate `limits`
      and `user_api` parameters for the specific use case of sequential BLAS
      calls within an OpenMP parallel region. The `user_api` parameter is
      ignored.

    - If None, this function does not do anything.

user_api : {USER_APIS} or None (default=None)
    APIs of libraries to limit. Used only if `limits` is an int.

    - If "blas", it will only limit BLAS supported libraries ({BLAS_LIBS}).

    - If "openmp", it will only limit OpenMP supported libraries
      ({OPENMP_LIBS}). Note that it can affect the number of threads used
      by the BLAS libraries if they rely on OpenMP.

    - If None, this function will apply to all supported libraries.
r†  )r…  ©r7   r‡  r<   s      r$   r²  ÚThreadpoolController.limitf  s   € ôf " $ÀÑIÐIr#   c              #   óD   #   • U  H  nS R                  U5      v •  M     g7frî  rï  rÎ  s     r$   rm   rð  œ  rñ  rò  c                ó*   • [         R                  XUS9$ )a  Change the maximal number of threads that can be used in thread pools.

This function returns an object that can be used as a decorator.

Set the maximal number of threads that can be used in thread pools used in
the supported libraries to `limits`. This function works for libraries that
are already loaded in the interpreter and can be changed dynamically.

Parameters
----------
limits : int, dict or None (default=None)
    The maximal number of threads that can be used in thread pools

    - If int, sets the maximum number of threads to `limits` for each
      library selected by `user_api`.

    - If it is a dictionary `{{key: max_threads}}`, this function sets a
      custom maximum number of threads for each `key` which can be either a
      `user_api` or a `prefix` for a specific library.

    - If None, this function does not do anything.

user_api : {USER_APIS} or None (default=None)
    APIs of libraries to limit. Used only if `limits` is an int.

    - If "blas", it will only limit BLAS supported libraries ({BLAS_LIBS}).

    - If "openmp", it will only limit OpenMP supported libraries
      ({OPENMP_LIBS}). Note that it can affect the number of threads used
      by the BLAS libraries if they rely on OpenMP.

    - If None, this function will apply to all supported libraries.
r†  )r…  rž  rô  s      r$   rž  ÚThreadpoolController.wrap›  s   € ôN "×&Ñ& tÀXÐ&ÐNÐNr#   c                 ó,   • [        U R                  5      $ rx   )r©  r¢  rG   s    r$   Ú__len__ÚThreadpoolController.__len__Ä  s   € Ü�4×'Ñ'Ó(Ð(r#   c                 ó  • [         R                  S:X  a  U R                  5         g[         R                  S:X  a  U R                  5         gS[         R                  ;   a  U R                  5         gU R                  5         g)zALoop through loaded shared libraries and store the supported onesÚdarwinÚwin32ÚpyodideN)ÚsysÚplatformÚ_find_libraries_with_dyldÚ+_find_libraries_with_enum_process_module_exÚmodulesÚ_find_libraries_pyodideÚ$_find_libraries_with_dl_iterate_phdrrG   s    r$   r  Ú$ThreadpoolController._load_librariesÇ  sV   € ä�<‰<˜8Ó#Ø×*Ñ*Õ,Ü�\‰\˜WÓ$Ø×<Ñ<Õ>Øœ#Ÿ+™+Ó%Ø×(Ñ(Õ*à×5Ñ5Õ7r#   c                 ó¢  ^ • T R                  5       n[        US5      (       d  [        R                  " S[        5        / $ U 4S jn[
        R                  " [
        R                  [
        R                  " [        5      [
        R                  [
        R                  5      nU" U5      n[
        R                  " S5      nUR                  XE5        g)a>  Loop through loaded libraries and return binders on supported ones

This function is expected to work on POSIX system only.
This code is adapted from code by Intel developer @anton-malakhov
available at https://github.com/IntelPython/smp

Copyright (c) 2017, Intel Corporation published under the BSD 3-Clause
license
Údl_iterate_phdrz9Could not find dl_iterate_phdr in the C standard library.c                 ó„   >• U R                   R                  nU(       a"  UR                  S5      nTR                  U5        g)Nr‹   r   )Úcontentsr   rŽ   Ú_make_controller_from_path)rD   ÚsizeÚdatar(   r7   s       €r$   Úmatch_library_callbackÚYThreadpoolController._find_libraries_with_dl_iterate_phdr.<locals>.match_library_callbackæ  s6   ø€ à—}‘}×.Ñ.ˆHÞØ#Ÿ?™?¨7Ó3�ð ×/Ñ/°Ô9Ør#   r#   N)Ú	_get_libcru   r¬  r­  ÚRuntimeWarningr   Ú	CFUNCTYPErË   ÚPOINTERr   Úc_size_tr   r	  )r7   Úlibcr  Úc_func_signatureÚc_match_library_callbackr  s   `     r$   r  Ú9ThreadpoolController._find_libraries_with_dl_iterate_phdrÒ  sœ   ø€ ð �~‰~ÓˆÜ�tÐ.×/Ñ/Ü�MŠMØKÜôð ˆIõ	ô "×+Ò+Ü�L‰LÜ�NŠNœ=Ó)Ü�O‰OÜ�O‰Oó	
Ðñ $4Ð4JÓ#KÐ ä�Š˜sÓ#ˆØ×ÑÐ5Õ<r#   c                 ó�  • U R                  5       n[        US5      (       d  [        R                  " S[        5        / $ UR                  5       n[        R                  UR                  l	        [        U5       HJ  n[        R                  " UR                  U5      5      nUR                  S5      nU R                  U5        ML     g)zyLoop through loaded libraries and return binders on supported ones

This function is expected to work on OSX system only
Ú_dyld_image_countz;Could not find _dyld_image_count in the C standard library.r‹   N)r  ru   r¬  r­  r  r  r   r   Ú_dyld_get_image_namerŒ   rý   Ú	string_atrŽ   r  )r7   r  Ún_dyldr  r(   s        r$   r  Ú.ThreadpoolController._find_libraries_with_dyldû  sž   € ð
 �~‰~ÓˆÜ�tÐ0×1Ñ1Ü�MŠMØMÜôð ˆIà×'Ñ'Ó)ˆÜ,2¯O©Oˆ×!Ñ!Ô)ä�v–ˆAÜ×'Ò'¨×(AÑ(AÀ!Ó(DÓEˆHØ—‘ wÓ/ˆHð ×+Ñ+¨HÖ5ò r#   c           	      óP  • SSK JnJnJn  SnSnSnU R	                  S5      nU R	                  S5      nUR                  XE-  S[        R                  " 5       5      n	U	(       d!  [        S	[        R                  " 5        35      e S
n
U" 5       n X*-  " 5       n[        R                  " U5      nUR                  U	[        R                  " U5      U[        R                  " U5      U5      (       d  [        S5      eXÛR                  :¼  a  OUR                  XÚ-  -  n
M�  UR                  XÚ-  -  n[        X,SU 5      nSU-  n[        R                  " U5      nU" 5       nU Hœ  nUR!                  U	U[        R                  " U5      [        R                  " U5      5      (       d  [        S5      eUR                  n[#        U5      U:X  a!  [$        R&                  " SU< 3[(        5        M‹  U R+                  U5        Mž     UR-                  U	5        g! UR-                  U	5        f = f)zöLoop through loaded libraries and return binders on supported ones

This function is expected to work on windows system only.
This code is adapted from code by Philipp Hagemeister @phihag available
at https://stackoverflow.com/questions/17474574
r   )ÚDWORDÚHMODULEÚMAX_PATHrû   é   rM  ÚPsapiÚkernel32FzCould not open PID é   zEnumProcessModulesEx failedNé
   zGetModuleFileNameEx failedzÜCould not get the full path of a dynamic library (path too long). This library will be ignored and threadpoolctl might not be able to control or display information about all loaded libraries. Here's the truncated path: )Úctypes.wintypesr!  r"  r#  Ú_get_windllÚOpenProcessr|  ÚgetpidÚOSErrorr   r  ÚEnumProcessModulesExró   rô   ÚmapÚcreate_unicode_bufferÚGetModuleFileNameExWr©  r¬  r­  r  r  ÚCloseHandle)r7   r!  r"  r#  ÚPROCESS_QUERY_INFORMATIONÚPROCESS_VM_READÚLIST_LIBRARIES_ALLÚps_apiÚ	kernel_32Ú	h_processÚ	buf_countÚneededÚbufÚbuf_sizeÚcountÚ	h_modulesÚmax_pathÚn_sizeÚh_moduler(   s                       r$   r  Ú@ThreadpoolController._find_libraries_with_enum_process_module_ex  s  € ÷ 	=Ñ<à$*Ð!Ø ˆà!Ðà×!Ñ! 'Ó*ˆØ×$Ñ$ ZÓ0ˆ	à×)Ñ)Ø%Ñ7¸ÄÇ	Â	Ãó
ˆ	ö ÜÐ/´·	²	³¨}Ð=Ó>Ð>ð1	-ØˆIÙ“WˆFð ØÒ*Ó-�Ü!Ÿ=š=¨Ó-�Ø×2Ñ2ØÜ—L’L Ó%ØÜ—L’L Ó(Ø&÷ñ ô "Ð"?Ó@Ð@ØŸ|™|Ó+ØØ"ŸL™L¨XÑ-BÑC�	ñ ð —L‘L XÑ%:Ñ;ˆEÜ˜G¨¨% [Ó1ˆIð
 ˜H‘}ˆHÜ×.Ò.¨xÓ8ˆCÙ“WˆFÛ%�à×2Ñ2Ø˜x¬¯ª°cÓ):¼F¿LºLÈÓ<P÷ñ ô "Ð">Ó?Ð?ØŸ9™9�ä�x“= HÓ,Ü—M’MðHð IQÁ|ðUô 'öð ×3Ñ3°HÖ=ñ% &ð( ×!Ñ! )Õ,øˆI×!Ñ! )Õ,ús   ÂE<H ÈH%c                 ó  •  SSK Jn  UR
                  R                  5        H:  n[        R                  R                  U5      (       d  M)  U R                  U5        M<     g! [         a    [        R                  " S5         gf = f)ar  Pyodide specific implementation for finding loaded libraries.

Adapted from suggestion in https://github.com/joblib/threadpoolctl/pull/169#issuecomment-1946696449.

One day, we may have a simpler solution. libc dl_iterate_phdr needs to
be implemented in Emscripten and exposed in Pyodide, see
https://github.com/emscripten-core/emscripten/issues/21354 for more
details.
r   )ÚLDSOzHUnable to import LDSO from pyodide_js._module. This should never happen.N)Úpyodide_js._modulerD  ÚImportErrorr¬  r­  ÚloadedLibsByNameÚas_object_mapr|  r}  Úexistsr  )r7   rD  r(   s      r$   r  Ú,ThreadpoolController._find_libraries_pyodide\  so   € ð	Ý/ð ×-Ñ-×;Ñ;Ö=ˆHô
 �w‰w�~‰~˜h×'Ó'Ø×/Ñ/°Ö9ò >øô ó 	Ü�MŠMðôñ ð	ús   ‚A! Á! BÂBc                 óv  ^^• [        U5      n[        R                  R                  U5      R	                  5       n[
         Hõ  nU R                  X#R                  5      nUc  M#  US:X  aZ  UR                  S5      (       aB  [        R                  " U[        5      m[        U4S jUR                   5       5      (       d  M€  OMƒ  U" XU S9mUS U R                   5       ;   a  M£  [        US5      (       a&  [        U4S jUR                   5       5      (       d  MÚ  U R                  R!                  T5        M÷     g)	z:Store a library controller if it is supported and selectedNrd   ú.dllc              3   ó<   >#   • U  H  n[        TU5      v •  M     g 7frx   )ru   )rk   Úfuncrd   s     €r$   rm   ÚBThreadpoolController._make_controller_from_path.<locals>.<genexpr>‘  s"   øé € ð â$B˜Dô   ¨×.Ð.Ú$Bùs   ƒr'   c              3   ó8   #   • U  H  oR                   v •  M     g 7frx   r  rf  s     r$   rm   rO  §  s   é € ÐIÒ4H¨SŸLžLÒ4Hùrh  r¢   c              3   óP   >#   • U  H  n[        TR                  U5      v •  M     g 7frx   )ru   r0   )rk   rN  r£  s     €r$   rm   rO  «  s)   øé € ð Eâ:�Dô ˜×-Ñ-¨t×4Ð4Ú:ùs   ƒ#&)r€  r|  r}  ÚbasenameÚlowerrk  Ú_check_prefixr    Úendswithr   r.   r/   rè  r¢   r¢  ru   rÿ   )r7   r(   ÚfilenameÚcontroller_classr)   r£  rd   s        @@r$   r  Ú/ThreadpoolController._make_controller_from_pathw  s'  ù€ ô ˜XÓ&ˆô —7‘7×#Ñ# HÓ-×3Ñ3Ó5ˆ÷ !1Ðà×'Ñ'¨×2TÑ2TÓUˆFð ‰~Ùð ˜Ó"Ø×$Ñ$ V×,Ñ,Ü$Ÿkšk¨(´LÓA�GÜô à$4×$BÒ$Bó÷ ñ ñ !ð	ñ ñ .Ø!¸ñˆNð ÑI°D×4HÒ4HÓIÓIáäÐ+¨_×=Ñ=Äô Eà,×:Ò:óE÷ Bó Bð ×$Ñ$×+Ñ+¨NÖ;ò] !1r#   c                 óJ   • U H  nUR                  U5      (       d  M  Us  $    g)zMReturn the prefix library_basename starts with

Return None if none matches.
N)Ú
startswith)r7   Úlibrary_basenamer    r)   s       r$   rT  Ú"ThreadpoolController._check_prefix±  s)   € ó
 (ˆFØ×*Ñ*¨6×2Ó2Ø’ñ (ð r#   c                 óÖ   • U R                    Vs/ s H  oR                  PM     nn[        R                  " S5      nSU;   a#  SU;   a  [        R
                  " U[        5        gggs  snf )z?Raise a warning if llvm-OpenMP and intel-OpenMP are both loadedaù  
            Found Intel OpenMP ('libiomp') and LLVM OpenMP ('libomp') loaded at
            the same time. Both libraries are known to be incompatible and this
            can cause random crashes or deadlocks on Linux when loaded in the
            same Python program.
            Using threadpoolctl may cause crashes or deadlocks. For more
            information and possible workarounds, please see
                https://github.com/joblib/threadpoolctl/blob/master/multiple_openmp.md
            rV  rT  N)r¢  r)   ÚtextwrapÚdedentr¬  r­  r  )r7   r£  rÀ  Úmsgs       r$   rÚ  Ú1ThreadpoolController._warn_if_incompatible_openmp»  sb   € à@D×@TÒ@TÓUÒ@T¨n×)Ô)Ñ@TˆÐUÜ�oŠoðó

ˆð �xÓ I°Ó$9Ü�MŠM˜#œ~Õ.ð %:Ðùò Vs   �A&c                 ó¢   • U R                   R                  S5      nUc0  [        R                  " [	        S5      [
        S9nXR                   S'   U$ )z Load the lib-C for unix systems.r  Úcr,   )Ú_system_librariesÚgetr   r.   r   r/   )r�  r  s     r$   r  ÚThreadpoolController._get_libcÌ  sI   € ð ×$Ñ$×(Ñ(¨Ó0ˆØ‰<ô —;’;œ|¨CÓ0´|ÑDˆDØ,0×!Ñ! &Ñ)Øˆr#   c                 ó�   • U R                   R                  U5      nUc'  [        R                  " U S35      nX R                   U'   U$ )zLoad a windows DLLrL  )rd  re  r   ÚWinDLL)r�  Údll_nameÚdlls      r$   r*  Ú ThreadpoolController._get_windllÛ  sG   € ð ×#Ñ#×'Ñ'¨Ó1ˆØ‰;Ü—-’- 8 *¨DÐ 1Ó2ˆCØ.1×!Ñ! (Ñ+Øˆ
r#   )r¢  ) r   r   r   r   r\   r½  rd  r8   rÅ  rß  rD   ré  r¸  ry  r®  rl  Ú_ALL_BLAS_LIBRARIESÚ_ALL_OPENMP_LIBRARIESr²  rž  rú  r  r  r  r  r  r  rT  rÚ  r  r*  r"   r   r#   r$   r   r   !  s2  † ññ ›Ðò,ð
 ñó ðò
RòGò6
1ñ Ø—)‘)ÑI¹.ÓIÓIØ—)‘)Ð/Ó0Ø—I‘IÐ3Ó4ñð
 #¨Tô .Jóð
.Jñ` Ø—)‘)ÑI¹.ÓIÓIØ—)‘)Ð/Ó0Ø—I‘IÐ3Ó4ñð
 "¨Dô "Oóð
"OòH)ò	8ò'=òR6ò.H-òT:ò68<òtò/ð" ñó ðð ñó ór#   r   c            	      óê  • SSK n SSKnSSKnSSKnU R	                  SSS9nUR                  SSSS	S
SS9  UR                  SSSS9  UR                  UR                  SS 5      nUR                   H  n UR                  USS9  M     UR                  (       a  [        UR                  5        [        UR                  [!        5       SS95        g! [         a    [        SXcR                  S9   M�  f = f)zBCommandline interface to display thread-pool information and exit.r   Nz5python -m threadpoolctl -i numpy scipy.linalg xgboostz)Display thread-pool information and exit.)ÚusageÚdescriptionz-iz--importr  Ú*r   z;Python modules to import before introspecting thread-pools.)ÚdestÚnargsÚdefaultÚhelpz-cz	--commandz@a Python statement to execute before introspecting thread-pools.)ru  rŠ   )ÚpackagezWARNING: could not import)Úfiler”   )Úindent)ÚargparseÚ	importlibÚjsonr   ÚArgumentParserÚadd_argumentÚ
parse_argsÚargvr  Úimport_modulerF  ÚprintÚstderrÚcommandÚexecÚdumpsr
   )ry  rz  r{  r   ÚparserÚoptionsÚmodules          r$   Ú_mainr‰  å  s   € ãÛÛÛà×$Ñ$ØEØ?ð %ð €Fð ×ÑØØØØØØJð ñ ð ×ÑØØØOð ñ ð ×Ñ §¡¨¨ Ó-€GØ—/”/ˆð	HØ×#Ñ# F°DÐ#Ó9ñ "ð ‡‡ÜˆW�_‰_Ôä	ˆ$�*‰*”_Ó&¨qˆ*Ð
1Õ2øô ó 	HÜÐ-¨v¿J¹JÕGð	Hús   Á4CÃC2Ã1C2Ú__main__)?r\   r|  r>  r   r   rq   r^  Útypingr   r¬  Úctypes.utilr   Úabcr   r   Ú	functoolsr   Ú
contextlibr   Ú__version__Ú__all__ÚenvironÚ
setdefaultrz  Úc_uint64Úc_uint32r   Úc_uint16r    Ú	Structurer   ÚRTLD_NOLOADr/   ÚAttributeErrorÚDEFAULT_MODEr   r_   r¤   rÎ   r%  rS  rk  r¼  r¨  rl  r=   rm  rn  r<   rl  r    rm  r   ry  r€  r
   r…  rœ  r®  r	   r   r‰  r   )rg  s   0r$   Ú<module>r›     s¥  ðñó 
Û 	Û 
Û Û Û Ý Û Ý $ß #Ý Ý 'à€ò€ð( ‡
�
× Ñ Ð,¨fÔ 5ð #&§+¡+°Ó"5ˆv�Š¸6¿?¹?€Ø'*§{¡{°UÓ':�F—O’OÀÇÁÐ ô�F×$Ñ$ô ð'Ø—>‘>€Lô
X
�Cô X
ôvE˜ô EôP<D�]ô <Dô~}L˜-ô }Lô@52�Mô 52ôp�}ô ð6 ØØØØðÐ ñ ‘cÑCÑ2BÓCÓCÓD€Ù2BÓCÒ2B¨3×&Ô&Ñ2BÑCÐ ÙÙÑOÑ*ÓOÓOó€ñ !1óÚ 0˜·L±LÀFÑ4JÓ€C×ÔÑ 0ñÐ ð )×:Ñ:Ð ò7òñ �5Ññ&ó ð&ñ
 ™T .Ó1ÐASÑTñ)ó Uð)÷$V<ñ V<ôrÐ"4Ð6Fô ñ$ Ø�i‰iÑ=©nÓ=Ó=Ø�i‰iÐ+Ó,Ø—	‘	Ð/Ó0ñô
4VÐ*ó 4Vóð
4V÷nAñ AòH#3ðL ˆzÓÙ	…Gð øðO& ó 'Ø×&Ñ&ƒLð'üòD Dùòs$   ÃH= Ä5IÅ&IÅ=IÈ=IÉI