| | 3776 | def _brute_force_four_squares(n): |
| | 3777 | """ |
| | 3778 | Brute force search for decomposition into a sum of four squares, |
| | 3779 | for cases that the main algorithm fails to handle. |
| | 3780 | |
| | 3781 | INPUT: a positive integer |
| | 3782 | OUTPUT: a list of four numbers whose squares sum to n |
| | 3783 | |
| | 3784 | EXAMPLES:: |
| | 3785 | sage: from sage.rings.arith import _brute_force_four_squares |
| | 3786 | sage: _brute_force_four_squares(567) |
| | 3787 | [1, 1, 6, 23] |
| | 3788 | """ |
| | 3789 | from math import sqrt |
| | 3790 | for i in range(0,int(sqrt(n))+1): |
| | 3791 | for j in range(i,int(sqrt(n-i**2))+1): |
| | 3792 | for k in range(j, int(sqrt(n-i**2-j**2))+1): |
| | 3793 | rem = n-i**2-j**2-k**2 |
| | 3794 | if rem >= 0: |
| | 3795 | l = int(sqrt(rem)) |
| | 3796 | if rem-l**2==0: |
| | 3797 | return [i,j,k,l] |
| | 3798 | |
| | 3799 | def four_squares(n): |
| | 3800 | """ |
| | 3801 | Computes the decomposition into the sum of four squares, |
| | 3802 | using an algorithm described by Peter Schorn at: |
| | 3803 | http://www.schorn.ch/howto.html. |
| | 3804 | |
| | 3805 | INPUT: an integer |
| | 3806 | |
| | 3807 | OUTPUT: a list of four numbers whose squares sum to n |
| | 3808 | |
| | 3809 | EXAMPLES:: |
| | 3810 | sage: four_squares(3) |
| | 3811 | [0, 1, 1, 1] |
| | 3812 | sage: four_squares(130) |
| | 3813 | [0, 0, 3, 11] |
| | 3814 | sage: four_squares(1101011011004) |
| | 3815 | [2, 1049178, 2370, 15196] |
| | 3816 | sage: sum([i-sum([q^2 for q in four_squares(i)]) for i in range(2,10000)]) # long time |
| | 3817 | 0 |
| | 3818 | """ |
| | 3819 | from sage.rings.integer_mod import mod |
| | 3820 | from math import sqrt |
| | 3821 | from sage.rings.arith import _brute_force_four_squares |
| | 3822 | try: |
| | 3823 | ts = two_squares(n) |
| | 3824 | return [0,0,ts[0],ts[1]] |
| | 3825 | except ValueError: |
| | 3826 | pass |
| | 3827 | m = n |
| | 3828 | v = 0 |
| | 3829 | while mod(m,4)==0: |
| | 3830 | v = v +1 |
| | 3831 | m = m/4 |
| | 3832 | if mod(m,8) == 7: |
| | 3833 | d = 1 |
| | 3834 | m = m - 1 |
| | 3835 | else: |
| | 3836 | d = 0 |
| | 3837 | if mod(m,8)==3: |
| | 3838 | x = int(sqrt(m)) |
| | 3839 | if mod(x,2) == 0: |
| | 3840 | x = x - 1 |
| | 3841 | p = (m-x**2)/2 |
| | 3842 | while not is_prime(p): |
| | 3843 | x = x - 2 |
| | 3844 | p = (m-x**2)/2 |
| | 3845 | if x < 0: |
| | 3846 | # fall back to brute force |
| | 3847 | m = m + d |
| | 3848 | return [2**v*q for q in _brute_force_four_squares(m)] |
| | 3849 | y,z = two_squares(p) |
| | 3850 | return [2**v*q for q in [d,x,y+z,abs(y-z)]] |
| | 3851 | x = int(sqrt(m)) |
| | 3852 | p = m - x**2 |
| | 3853 | if p == 1: |
| | 3854 | return[2**v*q for q in [d,0,x,1]] |
| | 3855 | while not is_prime(p): |
| | 3856 | x = x - 1 |
| | 3857 | p = m - x**2 |
| | 3858 | if x < 0: |
| | 3859 | # fall back to brute force |
| | 3860 | m = m + d |
| | 3861 | return [2**v*q for q in _brute_force_four_squares(m)] |
| | 3862 | y,z = two_squares(p) |
| | 3863 | return [2**v*q for q in [d,x,y,z]] |
| | 3864 | |
| | 3865 | |