����C %# , #&')*)-0-(0%()(��C (((((((((((((((((((((((((((((((((((((((((((((((((((����"�������@�@�hC��}!���Ѱ��<"� 9iׂIIIHk�+?�c?��*Y�����!�du)b�T�9вU�$8G��I.�澬��D���Sq� q�}.<��Z�l�V!X� *x�-�\����t3i�Ũ�sNv71�ƛ\��z|t�L���$�����*f��kʮ��7�H;���~F%�'3�@�H�q�` 9mOL����/x@ @��G
d�8F�ه��Ka�Kdr�Fh.�]y4 JЛ��]�K�B�E$��$ $ �PR�����G�]��u�i$�$���'! "#031���C/Td=S�Q?���62Ccj{ ����̏d�چ/c�V�`��Wz͈�{Y`�d�h�L �]OB���l���o���mr���n��s-ڗEZ��N�_��1%b���H�ϣ������V�7):�ӷ)�}�~�(�;�!�b1�5K��[E�vϻ>��q.%� ���O���(�c�#x�$�'+��`٥v��v(�����M�"�v��B��.�a ���T�~�ϕ�hy(6nݱl��1yNɓx�������AR�8�rqv1.cS�+��_���&@�� �u�M�5Ĉ�Xm���eL�X�q��y#�9]�c�}ɄL��d�eJ몓���I1T�d��CaM�$��T�,�X �bʭ�!�%F5��X1x#���!�q��\��F��2��&Rq���C�ol~�̱�.0ϦL�d�`.������ ���m{�Y~k{C��}bv�;U��c<�r�~ɜs�1�j��]W�l��*նCr��Q�N9�-������d��E؛��nF��eړ�8(q��5UgRȱGTA��*������̆��V�珰����ezN��h�U]�T�FG�^���<��ay�,!���5.� �u�bΚ�V�J%��m�Dxn'�����6�@BPa�`��Hts� �ɮ���Ŏ�Zɬ��%B�X��d5Z���hC}�䅸�p+ k=��ʒ(�aՏFG&�%@/�{+�Yu+�ȣGѩ"O%�|vȲxF>�N(��ou�h6 &Y5��8�7�E$-��']n,@TD\��+���Ry�U��U^�Q,f>��1�����q��f��U��� ����F���ڥ��>I�����fNUw�u��#OMMQ6� N�*��_�� k� ����rS��`���1�:��!�F'<+� � b?O��2 !Q12A��� "3a������#$��?�,�7�!`yǮ(�1�6w��a���� �F�#��?*"s���v>��Ⱥ����f�v��͑���s����������]Gn��S ���ȥpG ы�E�g�)Z���x�rY�q�]�@f�_܃�pչEڎّC ����Ŝ*/ �h�O�Sv�و\��5��U��y��|o�Hm2C�S�BW����)��5��{T��W���=o*RA��<����L0g4{��쁢�ep�rw�8��7��U���t<Ԍѻ7�fGf�k}���Ê�㛆Gռz�Q@��{C��'G��8�!�S$�j��x���|���צV<��,����u�k�uu�rM�f�_dϣi ߫�ԟn�!K����mxu�=�槻�'j�X�����������%!A "1QR#Br��?�R:��R�n�b[�II?#��6<:�$gN����lGNlrr��dעMMn`ɿy�,�%B�e�W��dVS��r���� %�tT��(�ɷ��S�]�O]#�_LEMHN�M���kv���~X���O6�U�V_�����b���J�t�774����D!1AQa"2q�#3BRb����0���� 4CSr����cst�����?��^q���7�dG�U�"p��moz��'��n_x���唹e������<6��O�t���R>k��s=�Cr���e�?�i��� ����/��ں$be���o`ޮ�GHy�;fNAl�8��.�\�S������"���a�úF�YvNk�-*`v�k�ʈ2f�EE��Wa�,� �fF^#�;��[9��^~������Y$:0#W3������Z*���I�Z�ڹ�k�n--9=��G��;7F)m{T�Ɇ��=�����Ȭ5�5�B�aڞ5M����#m�5Ʀ��m�8��+Hh���$�}�:&�e�Q�[;i]С�:�:��o����$<~��5RB�?�s3�5�r��O��ֿ�w�P/��̅���(�Z6�R>)��N��4�!ʊ�wz�-�r�w+�yk���q�1�bKhƸ�4N�Ӑ�X����Q��_��})�+e1�5��n��q?��[�^�9�<�z3Fsi�8�'�)9p)�{��RP�Z+�*��p(aY��V����6l�g�9��;���d�u���Nt@�3�sTwzaŇ�GT�b�H��(#��*zc�������9K�b1�����t����Ê��
�Z?g�iD���H�R���B���^M����v���O���L�D,'d�q�C�P�����$Δ��U�֟֊=�s��F�$��J�ދZ?�N��������A�N�WP��,�� �¦�&;�x��dup�����i���Ipd���;�Dž!��ֿѮAb%�u��}j��-p��>I�[�N�bi����G�'�;4w�m]H�]����#LӘNN��R��������s�.]��en��-�8e��Ps����Q��;���ț�E�ݫ���7��g�_L��W��EZ:/��I���a�g�n�ܤ��iٹ���ŷ�T���H~i�a�����֎�~KV������ A-2m]�F"�m�9-Zbǰ�״ @����~�4�N�[�Uxč�tl>������u#r�gѐ�3���;M9�<�J�����1�vfL8����1�P�HgP�Xv��������{����O�}�n��KQ؋����7<�l�fey<�}�>�bX���4<`Y7���si��V)�s�:�{�rO�h�z �@4VW�B���&�������ɡob܋�F��4>y�s�fXWS�N�O$�,.u:�ԫ��g�yao4��$h��D#��ٸf^kh�7�#1Z�֥&���*�v-��;bޭ����Q�����h�ow�y]�ه.+�7�M�ⴻ �JY��g�f�i3q��KC��3�¹�?5�Z.N��^Z w���KF͂���7��ރ۞��wj��T�J.�q��\Sv1U����R��욽&�N����pЖ`�`у��m`v�n#z��4��>e��V�`'���h�����'�j�AҔ�-�4:H���n]9�h<��n����U�6m��2c�E�1/�Y�%���I��~ʏ�|VBƟ@����;�������%�M9M���}��1�D��d����%g���O��]��у&�r��f�7�uܲ���(!1AQaq�������0� ���?!��*��@)�Je�G��j��{�['��v+���������)���(�/����д%젍Z��kk�Lu�Rm���j.c���@Z� V�J��d��j���h6���2AO�� a;oBu���H�=���nK�W8�B�ɰ�u?��бأm,�sr����|����8˨i��qI2tZ�ۄJP��XE��������zޔj~]UMu����zv!����N�&�1�Y��zJ�ՠ��\p��o'ሸ�C؊Y��TD"HM5�Ъ��i߯a���F����A)�����ڮ����z�E���@�hg�֝8�1jk��\�M�3�8ܢ�� ������s�7����N}�ޭ������GN�Bc���L pk�;�J�δ3�e�iU�gAYW]\�>�GyگQ=��f�KA;T�a`eM+Q �� �Ln���̌]GM�����<Ħ�j���H��N�M�x�}aX{̣S� ��ԅ��n�MA�S�r�(����(�L��zo9���.�;
�ӳf������`Ӕ٢3�� IW��\9~_���saa�\ԊW�ܭX:���ӆ�38�ty*����N�qP����BI�Y��jE��>DP�!�R%-��4��'�皺;��~J�!�7m���X��h�P!曭���$�\�AYj�.lC��4��+�jD�dgC0-*���|��`ZD�+л�C"��)��s��8Kq�pq���Ms��4� ��7\U`�.��[Ey8��AH!/��,���(:M -�T䓥�~O�4-���Ԓn��}HDN7���K���$�_Ԕ䚞`�R�hB�_aX?4V��ŗ�@ه�u�a�;�{PcT+�������7YBo�?��r-ͩ{�ĎA�� ����˼n��M286��G���1���V�˜Jв"l��V5���5�C]h���̊�A���%� �'p���Ԃ���Ր��9=�d�=�e�{�'<3�_ �:^�~��4�(�n�-C�s��5m![�jmIqU�~�Tw8��`���p�H8�u�Д l m�aP�0�������9y����CM��F1G糞�.�U~�������FC�{�!e(Y�:���P����7~;�L�N^{�1r�\���ԬG(���0d�ÏO�qK�Z�⑼�T�{ 2��s��Kd�Տ?mMQ��=���6�7�i�����H+����9��d��=��;�QؤH8n�Lb�D��yS%�(�{b���Cu���p�t#C���$A"�H{���jqᶯ�:�n=E����hH�`�!�m��MA������?�v6���+MԿ⟚qK�i�D�*Q5��CZ���2�|]�:Xd+�t�:o@��M��� :�32��b����[\5=�ֵ7])�|t��Ϻ����w�B�ń�e���!`�:��I,��9:����j@/a 8����+<�u�(T^ۺ~��2oE�B�%b)��z��ݳځ�)��i�j��&��Fi`qr��w���7�@��P�� �3Z&<�m�S�C����7t�T����ƴ�q~J�e�r6�Z]�rL���ه�E17'�x���+[�ܜTc6�/�����W�`�qpMJ���N5^����x�}{l�Fm������1�oZ\�����/d�/6� �uӸ�0elXuX;M��$M�}mB��������Z%e���3f�js����O�J~2�z�86�*PB��v�Ν��e-��.�/��L�O����2����9���4}|��T5M���hÐ7�F*��l+y0����:|��=k[�d�;|�ԉe�=w�<��õ�<��'!1AQaq����� ������?��5����)�(���+>v����6&{���Ǹ@����M�����v��iA 6T'�w��h�s �E}�x��G&'g�� J~1q�f�f���&��q˘���-���vYm
�/i1 �I��6��u,)�#�,����l}*&`�$�ͬe�%�w3�x�Ѥ�Xc�D��执g�峕�5B/�|$��=���%8 a��2.l� c�@G� �\�/x[өq�]�v5?�����N|�!���\��,>��{�"r�/��?��&!1QAa�� ��ᑱ����?ĊD�肭�� nv@�yޝ (�����I ����U - ���b�m�E>,��1v!�d�&�� ���&�檔�5D�&0P��Ԕ�͒@Z��:E"� Q��`>PH:~�O�����P�3W��@hM��k�U��\�O��R�������5ʄ�,��f�|��r���}јxo)�"+h�QK���/��0�`�5�{M~�� ���'!1AQaq���0 �������?�?�k��#^�~�G��#V,������#Z�1'ܤ����������~p�O%O�O�\�q�`�~��}��E�Ű5 �輸�du����x\�$���s[�{T2t`B��gq�4Z]b� 㛪�3,(@����bAp�r)9:@|b�!r�g:N�^�Ʌ��� �x_�\��pm7I��0?>^k��������w���|.K�[sF@�]Gn*L �yO� le�P�.p��֍�j�S�=�ʨ�ןQF�"��5zʼn���k�*8�u" ����Fg��� �cSy�V������Ƈ��N��ؐ(�����48hV�A�ӎ^��^ ���jyB� ��p"�����y]�ļlU�(�7�U`3�pCGF'&yg������o��z������X��ν:�P"@�G@x[��o&MJ�$F.����hi w;}�/^͇q���n�mN�/�TQ���އ��O1\,}��bQ #¯^S!)��X���#GPȏ�t�� c^\��' }iIZ���a�)��������z��4͊�Ξy��48,��f���#�����KP!Jx�|w�ʆ�������������#��Z�������< �~K��r�p&qH/;�R���沽�+�E�R���~0v���V#ʀ�T��S(-ڝ��B�y�b�C�D������b��������8��~�= �Y�ͧ]��@n����M�k2�%�;�%,�r6�LR腻?^��;KŇ=�ք ���=`�ɥ��/����z�&�I{���#J��M���C��}�H9^UJ�,P ��pS����G�d69Ϭu���%"��ˢP��K�"k)��=��9� ����㇌,��Oli��Xzh� " � ������R��^�s����N�k��Q>�63(���� ��PQ�Py�����3����$f+W՛=4�ǁ`*��^��Eb�K�t�6��^��!�籷��ȭ��K{/;�L���p�x�����;a���Oلz�[�.NP4�]Gc�T�v����~sg'LED��]j��'�G�]�6rY����UPw�*O�İՋi�'8�۴�#g�Xx+=�eU6�R��c�"�u2��~�?n�y�;�u��3�'��6�f������b��߬M�$*��k&?6���*^1n����ێz)<��Gz� �����7����Y� ��ۃ)$A��2�L6� ե�H�<�r��#ʽ2��O��R���z�A��XW��@���������<�G� Ϥ�^�˓i�M�W���6 ��0��m){c�;ݧ�>R�a����}1�ٯ%�EY2�Q��Ep���$ ��E��qS��t#+x� *�h�UI��XM?�'//��a'�G�����q@���<��z��؟����cd��z�ˬT_u�Ѯ����&�z�k ��n ]�a%�py»�`Qd�xc������n�� ��*��oTd�;'j�<�!j���'�(~�ʹW�M� P�mȘ��@֨V+��R�`�$��`�+@��_[�kG����P���Zh9�R����&5b�v���Z���#p�&�Ա+��8�etZ7G���;��@"�e0���v7����?��z�?_���_�q1�T�"�p�ˎ/U 6_�B�>��0( ��}G#������Ȣ�p�� �9��;/& `�B&$�y��t(�*z�x���Ӕ������S�?Kȏ3���{p� b � ۍ-�z܈֦��6?<���ǬP�N�G �更� �6�/h�����0Z���������i�ua��e�*M'A� �x��v�q.>�F� oN{��Q���{gD��L��u��=|���O xN���d���q�8(��E�Uu��,��O� t�DJ ����;��G����e���C��VYZ�� ���T4{����(�Ӳ'c�t�f��w�c�jr�e�m �#7,�6��B�E4Q�P�.P�(&��^{9H-�m�o ��q�g1���=��>p�)/"p0!4�mS6ú�FN���h��D �)��XdT �FؤZ⸚�k���H�c8v� <���u�P�Հ���:��_�EN��|�ӛ��u?-�/�o�Lhk�ܸ�S�;�Rī�����T"�N����M��px7<�� j�$��`�Y)Pjh 5` K�Qf�4�C�bX"�D���;HD�Z�9R b�F)�UA����v�#��HD�!{������>I� �`�ԁ i�4�)t*�ç�Le�_���>ru�GEQg��ǔct��ō0��l6v���d�� ��GG8���v^�|�#JyZPSO�� Y�CuAߐ�"�x���OfHF@�K�V�!少Eҕ]h� ��[���)��.q����*0I<8��^�6�}p��^tho���ig�i����DK���p,��2�3�I��5����쓄OY�6s7Qs�Ow^�w�J/�A➰������0������g(Մ��y��Kԇ����QS��?H���w�X�=��ҞX�~���Q=�'���p?7�@g�~�G�}�r��g�T?���
One Hat Cyber Team
One Hat Cyber Team
Your IP :
18.219.53.201
Server IP :
162.0.235.113
Server :
Linux premium146.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software :
LiteSpeed
PHP Version :
5.6.40
Buat File
|
Buat Folder
Dir :
~
/
opt
/
alt
/
ruby22
/
lib64
/
ruby
/
2.2.0
/
matrix
/
Edit File Name:
eigenvalue_decomposition.rb
class Matrix # Adapted from JAMA: http://math.nist.gov/javanumerics/jama/ # Eigenvalues and eigenvectors of a real matrix. # # Computes the eigenvalues and eigenvectors of a matrix A. # # If A is diagonalizable, this provides matrices V and D # such that A = V*D*V.inv, where D is the diagonal matrix with entries # equal to the eigenvalues and V is formed by the eigenvectors. # # If A is symmetric, then V is orthogonal and thus A = V*D*V.t class EigenvalueDecomposition # Constructs the eigenvalue decomposition for a square matrix +A+ # def initialize(a) # @d, @e: Arrays for internal storage of eigenvalues. # @v: Array for internal storage of eigenvectors. # @h: Array for internal storage of nonsymmetric Hessenberg form. raise TypeError, "Expected Matrix but got #{a.class}" unless a.is_a?(Matrix) @size = a.row_count @d = Array.new(@size, 0) @e = Array.new(@size, 0) if (@symmetric = a.symmetric?) @v = a.to_a tridiagonalize diagonalize else @v = Array.new(@size) { Array.new(@size, 0) } @h = a.to_a @ort = Array.new(@size, 0) reduce_to_hessenberg hessenberg_to_real_schur end end # Returns the eigenvector matrix +V+ # def eigenvector_matrix Matrix.send(:new, build_eigenvectors.transpose) end alias v eigenvector_matrix # Returns the inverse of the eigenvector matrix +V+ # def eigenvector_matrix_inv r = Matrix.send(:new, build_eigenvectors) r = r.transpose.inverse unless @symmetric r end alias v_inv eigenvector_matrix_inv # Returns the eigenvalues in an array # def eigenvalues values = @d.dup @e.each_with_index{|imag, i| values[i] = Complex(values[i], imag) unless imag == 0} values end # Returns an array of the eigenvectors # def eigenvectors build_eigenvectors.map{|ev| Vector.send(:new, ev)} end # Returns the block diagonal eigenvalue matrix +D+ # def eigenvalue_matrix Matrix.diagonal(*eigenvalues) end alias d eigenvalue_matrix # Returns [eigenvector_matrix, eigenvalue_matrix, eigenvector_matrix_inv] # def to_ary [v, d, v_inv] end alias_method :to_a, :to_ary private def build_eigenvectors # JAMA stores complex eigenvectors in a strange way # See http://web.archive.org/web/20111016032731/http://cio.nist.gov/esd/emaildir/lists/jama/msg01021.html @e.each_with_index.map do |imag, i| if imag == 0 Array.new(@size){|j| @v[j][i]} elsif imag > 0 Array.new(@size){|j| Complex(@v[j][i], @v[j][i+1])} else Array.new(@size){|j| Complex(@v[j][i-1], -@v[j][i])} end end end # Complex scalar division. def cdiv(xr, xi, yr, yi) if (yr.abs > yi.abs) r = yi/yr d = yr + r*yi [(xr + r*xi)/d, (xi - r*xr)/d] else r = yr/yi d = yi + r*yr [(r*xr + xi)/d, (r*xi - xr)/d] end end # Symmetric Householder reduction to tridiagonal form. def tridiagonalize # This is derived from the Algol procedures tred2 by # Bowdler, Martin, Reinsch, and Wilkinson, Handbook for # Auto. Comp., Vol.ii-Linear Algebra, and the corresponding # Fortran subroutine in EISPACK. @size.times do |j| @d[j] = @v[@size-1][j] end # Householder reduction to tridiagonal form. (@size-1).downto(0+1) do |i| # Scale to avoid under/overflow. scale = 0.0 h = 0.0 i.times do |k| scale = scale + @d[k].abs end if (scale == 0.0) @e[i] = @d[i-1] i.times do |j| @d[j] = @v[i-1][j] @v[i][j] = 0.0 @v[j][i] = 0.0 end else # Generate Householder vector. i.times do |k| @d[k] /= scale h += @d[k] * @d[k] end f = @d[i-1] g = Math.sqrt(h) if (f > 0) g = -g end @e[i] = scale * g h -= f * g @d[i-1] = f - g i.times do |j| @e[j] = 0.0 end # Apply similarity transformation to remaining columns. i.times do |j| f = @d[j] @v[j][i] = f g = @e[j] + @v[j][j] * f (j+1).upto(i-1) do |k| g += @v[k][j] * @d[k] @e[k] += @v[k][j] * f end @e[j] = g end f = 0.0 i.times do |j| @e[j] /= h f += @e[j] * @d[j] end hh = f / (h + h) i.times do |j| @e[j] -= hh * @d[j] end i.times do |j| f = @d[j] g = @e[j] j.upto(i-1) do |k| @v[k][j] -= (f * @e[k] + g * @d[k]) end @d[j] = @v[i-1][j] @v[i][j] = 0.0 end end @d[i] = h end # Accumulate transformations. 0.upto(@size-1-1) do |i| @v[@size-1][i] = @v[i][i] @v[i][i] = 1.0 h = @d[i+1] if (h != 0.0) 0.upto(i) do |k| @d[k] = @v[k][i+1] / h end 0.upto(i) do |j| g = 0.0 0.upto(i) do |k| g += @v[k][i+1] * @v[k][j] end 0.upto(i) do |k| @v[k][j] -= g * @d[k] end end end 0.upto(i) do |k| @v[k][i+1] = 0.0 end end @size.times do |j| @d[j] = @v[@size-1][j] @v[@size-1][j] = 0.0 end @v[@size-1][@size-1] = 1.0 @e[0] = 0.0 end # Symmetric tridiagonal QL algorithm. def diagonalize # This is derived from the Algol procedures tql2, by # Bowdler, Martin, Reinsch, and Wilkinson, Handbook for # Auto. Comp., Vol.ii-Linear Algebra, and the corresponding # Fortran subroutine in EISPACK. 1.upto(@size-1) do |i| @e[i-1] = @e[i] end @e[@size-1] = 0.0 f = 0.0 tst1 = 0.0 eps = Float::EPSILON @size.times do |l| # Find small subdiagonal element tst1 = [tst1, @d[l].abs + @e[l].abs].max m = l while (m < @size) do if (@e[m].abs <= eps*tst1) break end m+=1 end # If m == l, @d[l] is an eigenvalue, # otherwise, iterate. if (m > l) iter = 0 begin iter = iter + 1 # (Could check iteration count here.) # Compute implicit shift g = @d[l] p = (@d[l+1] - g) / (2.0 * @e[l]) r = Math.hypot(p, 1.0) if (p < 0) r = -r end @d[l] = @e[l] / (p + r) @d[l+1] = @e[l] * (p + r) dl1 = @d[l+1] h = g - @d[l] (l+2).upto(@size-1) do |i| @d[i] -= h end f += h # Implicit QL transformation. p = @d[m] c = 1.0 c2 = c c3 = c el1 = @e[l+1] s = 0.0 s2 = 0.0 (m-1).downto(l) do |i| c3 = c2 c2 = c s2 = s g = c * @e[i] h = c * p r = Math.hypot(p, @e[i]) @e[i+1] = s * r s = @e[i] / r c = p / r p = c * @d[i] - s * g @d[i+1] = h + s * (c * g + s * @d[i]) # Accumulate transformation. @size.times do |k| h = @v[k][i+1] @v[k][i+1] = s * @v[k][i] + c * h @v[k][i] = c * @v[k][i] - s * h end end p = -s * s2 * c3 * el1 * @e[l] / dl1 @e[l] = s * p @d[l] = c * p # Check for convergence. end while (@e[l].abs > eps*tst1) end @d[l] = @d[l] + f @e[l] = 0.0 end # Sort eigenvalues and corresponding vectors. 0.upto(@size-2) do |i| k = i p = @d[i] (i+1).upto(@size-1) do |j| if (@d[j] < p) k = j p = @d[j] end end if (k != i) @d[k] = @d[i] @d[i] = p @size.times do |j| p = @v[j][i] @v[j][i] = @v[j][k] @v[j][k] = p end end end end # Nonsymmetric reduction to Hessenberg form. def reduce_to_hessenberg # This is derived from the Algol procedures orthes and ortran, # by Martin and Wilkinson, Handbook for Auto. Comp., # Vol.ii-Linear Algebra, and the corresponding # Fortran subroutines in EISPACK. low = 0 high = @size-1 (low+1).upto(high-1) do |m| # Scale column. scale = 0.0 m.upto(high) do |i| scale = scale + @h[i][m-1].abs end if (scale != 0.0) # Compute Householder transformation. h = 0.0 high.downto(m) do |i| @ort[i] = @h[i][m-1]/scale h += @ort[i] * @ort[i] end g = Math.sqrt(h) if (@ort[m] > 0) g = -g end h -= @ort[m] * g @ort[m] = @ort[m] - g # Apply Householder similarity transformation # @h = (I-u*u'/h)*@h*(I-u*u')/h) m.upto(@size-1) do |j| f = 0.0 high.downto(m) do |i| f += @ort[i]*@h[i][j] end f = f/h m.upto(high) do |i| @h[i][j] -= f*@ort[i] end end 0.upto(high) do |i| f = 0.0 high.downto(m) do |j| f += @ort[j]*@h[i][j] end f = f/h m.upto(high) do |j| @h[i][j] -= f*@ort[j] end end @ort[m] = scale*@ort[m] @h[m][m-1] = scale*g end end # Accumulate transformations (Algol's ortran). @size.times do |i| @size.times do |j| @v[i][j] = (i == j ? 1.0 : 0.0) end end (high-1).downto(low+1) do |m| if (@h[m][m-1] != 0.0) (m+1).upto(high) do |i| @ort[i] = @h[i][m-1] end m.upto(high) do |j| g = 0.0 m.upto(high) do |i| g += @ort[i] * @v[i][j] end # Double division avoids possible underflow g = (g / @ort[m]) / @h[m][m-1] m.upto(high) do |i| @v[i][j] += g * @ort[i] end end end end end # Nonsymmetric reduction from Hessenberg to real Schur form. def hessenberg_to_real_schur # This is derived from the Algol procedure hqr2, # by Martin and Wilkinson, Handbook for Auto. Comp., # Vol.ii-Linear Algebra, and the corresponding # Fortran subroutine in EISPACK. # Initialize nn = @size n = nn-1 low = 0 high = nn-1 eps = Float::EPSILON exshift = 0.0 p=q=r=s=z=0 # Store roots isolated by balanc and compute matrix norm norm = 0.0 nn.times do |i| if (i < low || i > high) @d[i] = @h[i][i] @e[i] = 0.0 end ([i-1, 0].max).upto(nn-1) do |j| norm = norm + @h[i][j].abs end end # Outer loop over eigenvalue index iter = 0 while (n >= low) do # Look for single small sub-diagonal element l = n while (l > low) do s = @h[l-1][l-1].abs + @h[l][l].abs if (s == 0.0) s = norm end if (@h[l][l-1].abs < eps * s) break end l-=1 end # Check for convergence # One root found if (l == n) @h[n][n] = @h[n][n] + exshift @d[n] = @h[n][n] @e[n] = 0.0 n-=1 iter = 0 # Two roots found elsif (l == n-1) w = @h[n][n-1] * @h[n-1][n] p = (@h[n-1][n-1] - @h[n][n]) / 2.0 q = p * p + w z = Math.sqrt(q.abs) @h[n][n] = @h[n][n] + exshift @h[n-1][n-1] = @h[n-1][n-1] + exshift x = @h[n][n] # Real pair if (q >= 0) if (p >= 0) z = p + z else z = p - z end @d[n-1] = x + z @d[n] = @d[n-1] if (z != 0.0) @d[n] = x - w / z end @e[n-1] = 0.0 @e[n] = 0.0 x = @h[n][n-1] s = x.abs + z.abs p = x / s q = z / s r = Math.sqrt(p * p+q * q) p /= r q /= r # Row modification (n-1).upto(nn-1) do |j| z = @h[n-1][j] @h[n-1][j] = q * z + p * @h[n][j] @h[n][j] = q * @h[n][j] - p * z end # Column modification 0.upto(n) do |i| z = @h[i][n-1] @h[i][n-1] = q * z + p * @h[i][n] @h[i][n] = q * @h[i][n] - p * z end # Accumulate transformations low.upto(high) do |i| z = @v[i][n-1] @v[i][n-1] = q * z + p * @v[i][n] @v[i][n] = q * @v[i][n] - p * z end # Complex pair else @d[n-1] = x + p @d[n] = x + p @e[n-1] = z @e[n] = -z end n -= 2 iter = 0 # No convergence yet else # Form shift x = @h[n][n] y = 0.0 w = 0.0 if (l < n) y = @h[n-1][n-1] w = @h[n][n-1] * @h[n-1][n] end # Wilkinson's original ad hoc shift if (iter == 10) exshift += x low.upto(n) do |i| @h[i][i] -= x end s = @h[n][n-1].abs + @h[n-1][n-2].abs x = y = 0.75 * s w = -0.4375 * s * s end # MATLAB's new ad hoc shift if (iter == 30) s = (y - x) / 2.0 s *= s + w if (s > 0) s = Math.sqrt(s) if (y < x) s = -s end s = x - w / ((y - x) / 2.0 + s) low.upto(n) do |i| @h[i][i] -= s end exshift += s x = y = w = 0.964 end end iter = iter + 1 # (Could check iteration count here.) # Look for two consecutive small sub-diagonal elements m = n-2 while (m >= l) do z = @h[m][m] r = x - z s = y - z p = (r * s - w) / @h[m+1][m] + @h[m][m+1] q = @h[m+1][m+1] - z - r - s r = @h[m+2][m+1] s = p.abs + q.abs + r.abs p /= s q /= s r /= s if (m == l) break end if (@h[m][m-1].abs * (q.abs + r.abs) < eps * (p.abs * (@h[m-1][m-1].abs + z.abs + @h[m+1][m+1].abs))) break end m-=1 end (m+2).upto(n) do |i| @h[i][i-2] = 0.0 if (i > m+2) @h[i][i-3] = 0.0 end end # Double QR step involving rows l:n and columns m:n m.upto(n-1) do |k| notlast = (k != n-1) if (k != m) p = @h[k][k-1] q = @h[k+1][k-1] r = (notlast ? @h[k+2][k-1] : 0.0) x = p.abs + q.abs + r.abs next if x == 0 p /= x q /= x r /= x end s = Math.sqrt(p * p + q * q + r * r) if (p < 0) s = -s end if (s != 0) if (k != m) @h[k][k-1] = -s * x elsif (l != m) @h[k][k-1] = -@h[k][k-1] end p += s x = p / s y = q / s z = r / s q /= p r /= p # Row modification k.upto(nn-1) do |j| p = @h[k][j] + q * @h[k+1][j] if (notlast) p += r * @h[k+2][j] @h[k+2][j] = @h[k+2][j] - p * z end @h[k][j] = @h[k][j] - p * x @h[k+1][j] = @h[k+1][j] - p * y end # Column modification 0.upto([n, k+3].min) do |i| p = x * @h[i][k] + y * @h[i][k+1] if (notlast) p += z * @h[i][k+2] @h[i][k+2] = @h[i][k+2] - p * r end @h[i][k] = @h[i][k] - p @h[i][k+1] = @h[i][k+1] - p * q end # Accumulate transformations low.upto(high) do |i| p = x * @v[i][k] + y * @v[i][k+1] if (notlast) p += z * @v[i][k+2] @v[i][k+2] = @v[i][k+2] - p * r end @v[i][k] = @v[i][k] - p @v[i][k+1] = @v[i][k+1] - p * q end end # (s != 0) end # k loop end # check convergence end # while (n >= low) # Backsubstitute to find vectors of upper triangular form if (norm == 0.0) return end (nn-1).downto(0) do |n| p = @d[n] q = @e[n] # Real vector if (q == 0) l = n @h[n][n] = 1.0 (n-1).downto(0) do |i| w = @h[i][i] - p r = 0.0 l.upto(n) do |j| r += @h[i][j] * @h[j][n] end if (@e[i] < 0.0) z = w s = r else l = i if (@e[i] == 0.0) if (w != 0.0) @h[i][n] = -r / w else @h[i][n] = -r / (eps * norm) end # Solve real equations else x = @h[i][i+1] y = @h[i+1][i] q = (@d[i] - p) * (@d[i] - p) + @e[i] * @e[i] t = (x * s - z * r) / q @h[i][n] = t if (x.abs > z.abs) @h[i+1][n] = (-r - w * t) / x else @h[i+1][n] = (-s - y * t) / z end end # Overflow control t = @h[i][n].abs if ((eps * t) * t > 1) i.upto(n) do |j| @h[j][n] = @h[j][n] / t end end end end # Complex vector elsif (q < 0) l = n-1 # Last vector component imaginary so matrix is triangular if (@h[n][n-1].abs > @h[n-1][n].abs) @h[n-1][n-1] = q / @h[n][n-1] @h[n-1][n] = -(@h[n][n] - p) / @h[n][n-1] else cdivr, cdivi = cdiv(0.0, -@h[n-1][n], @h[n-1][n-1]-p, q) @h[n-1][n-1] = cdivr @h[n-1][n] = cdivi end @h[n][n-1] = 0.0 @h[n][n] = 1.0 (n-2).downto(0) do |i| ra = 0.0 sa = 0.0 l.upto(n) do |j| ra = ra + @h[i][j] * @h[j][n-1] sa = sa + @h[i][j] * @h[j][n] end w = @h[i][i] - p if (@e[i] < 0.0) z = w r = ra s = sa else l = i if (@e[i] == 0) cdivr, cdivi = cdiv(-ra, -sa, w, q) @h[i][n-1] = cdivr @h[i][n] = cdivi else # Solve complex equations x = @h[i][i+1] y = @h[i+1][i] vr = (@d[i] - p) * (@d[i] - p) + @e[i] * @e[i] - q * q vi = (@d[i] - p) * 2.0 * q if (vr == 0.0 && vi == 0.0) vr = eps * norm * (w.abs + q.abs + x.abs + y.abs + z.abs) end cdivr, cdivi = cdiv(x*r-z*ra+q*sa, x*s-z*sa-q*ra, vr, vi) @h[i][n-1] = cdivr @h[i][n] = cdivi if (x.abs > (z.abs + q.abs)) @h[i+1][n-1] = (-ra - w * @h[i][n-1] + q * @h[i][n]) / x @h[i+1][n] = (-sa - w * @h[i][n] - q * @h[i][n-1]) / x else cdivr, cdivi = cdiv(-r-y*@h[i][n-1], -s-y*@h[i][n], z, q) @h[i+1][n-1] = cdivr @h[i+1][n] = cdivi end end # Overflow control t = [@h[i][n-1].abs, @h[i][n].abs].max if ((eps * t) * t > 1) i.upto(n) do |j| @h[j][n-1] = @h[j][n-1] / t @h[j][n] = @h[j][n] / t end end end end end end # Vectors of isolated roots nn.times do |i| if (i < low || i > high) i.upto(nn-1) do |j| @v[i][j] = @h[i][j] end end end # Back transformation to get eigenvectors of original matrix (nn-1).downto(low) do |j| low.upto(high) do |i| z = 0.0 low.upto([j, high].min) do |k| z += @v[i][k] * @h[k][j] end @v[i][j] = z end end end end end
Save