SageMath: Mod().sqrt() prefixed with "sqrt" string for a particular combination in Sagemath. Is this a bug? - cryptography

Using Sagemath 9.2 on Windows 10
a1 = 9798722381116618056227637476565566484018606253194222755351973203508462742253522311154076194134700145275527578605535821781545038187843569198505993524407287520970070771172279404172004212310432500247465608472105231701909612623072343883942216806934904529600639676698348239426243771486521532222069409611514728756060897629936844695006373653175992634673678639333010508845045985607328371180356262460490393317997708599757357055386370808544031455931154122353547239678217006604692623467390849309525705453042722141078914816760002281629323554959490483823338710209710265138177331357093216148991708169324688688552846634664517554736
n = 27772857409875257529415990911214211975844307184430241451899407838750503024323367895540981606586709985980003435082116995888017731426634845808624796292507989171497629109450825818587383112280639037484593490692935998202437639626747133650990603333094513531505209954273004473567193235535061942991750932725808679249964667090723480397916715320876867803719301313440005075056481203859010490836599717523664197112053206745235908610484907715210436413015546671034478367679465233737115549451849810421017181842615880836253875862101545582922437858358265964489786463923280312860843031914516061327752183283528015684588796400861331354873
a2 = Mod(a1, n).sqrt()
I get the following
sage: print(a2)
sqrt9798722381116618056227637476565566484018606253194222755351973203508462742253522311154076194134700145275527578605535821781545038187843569198505993524407287520970070771172279404172004212310432500247465608472105231701909612623072343883942216806934904529600639676698348239426243771486521532222069409611514728756060897629936844695006373653175992634673678639333010508845045985607328371180356262460490393317997708599757357055386370808544031455931154122353547239678217006604692623467390849309525705453042722141078914816760002281629323554959490483823338710209710265138177331357093216148991708169324688688552846634664517554736
If you observe, a2 is prefixed with sqrt!
I don't see this with other roots, I calculated with Sage. What does this mean?
Is this a bug or does this have some other meaning?

It would appear n is prime (at least pseudo-prime):
sage: n.is_prime(proof=False)
True
Assuming it is, let us define the finite field in n elements:
sage: F = GF(n, proof=False)
and view a1 as an element A1 in F:
sage: A1 = F(a1)
Asking whether a1 is a square modulo n
amounts to asking whether A1 a square in F.
sage: A1.is_square()
False
It is not! So when we compute the square root of A1,
it has to be in a quadratic extension of F.
This is why when we ask Sage to compute this square root,
it gives it as a generator of that extension.
A natural name for this generator is "sqrt(n)",
which is what Sage uses.
Probably, when you computed other square roots,
they were square roots of numbers which were
squares modulo n, and therefore the square roots
could be computed in F, i.e. in ZZ / n ZZ,
without requiring a quadratic field extension.

Related

Unnormalizing in Knuth's Algorithm D

I'm trying to implement Algorithm D from Knuth's "The Art of Computer Programming, Vol 2" in Rust although I'm having trouble understating how to implement the very last step of unnormalizing. My natural numbers are a class where each number is a vector of u64, in base u64::MAX. Addition, subtraction, and multiplication have been implemented.
Knuth's Algorithm D is a euclidean division algorithm which takes two natural numbers x and y and returns (q,r) where q = x / y (integer division) and r = x % y, the remainder. The algorithm depends on an approximation method which only works if the first digit of y is greater than b/2, where b is the base you're representing the numbers in. Since not all numbers are of this form, it uses a "normalizing trick", for example (if we were in base 10) instead of doing 200 / 23, we calculate a normalizer d and do (200 * d) / (23 * d) so that 23 * d has a first digit greater than b/2.
So when we use the approximation method, we end up with the desired q but the remainder is multiplied by a factor of d. So the last step is to divide r by d so that we can get the q and r we want. My problem is, I'm a bit confused at how we're suppose to do this last step as it requires division and the method it's part of is trying to implement division.
(Maybe helpful?):
The way that d is calculated is just by taking the integer floor of b-1 divided by the first digit of y. However, Knuth suggests that it's possible to make d a power of 2, as long as d * the first digit of y is greater than b / 2. I think he makes this suggestion so that instead of dividing, we can just do a binary shift for this last step. Although I don't think I can do that given that my numbers are represented as vectors of u64 values, instead of binary.
Any suggestions?

Fast algorithm for computing cofactor matrix

I wonder if there is a fast algorithm, say (O(n^3)) for computing the cofactor matrix (or conjugate matrix) of a N*N square matrix. And yes one could first compute its determinant and inverse separately and then multiply them together. But how about this square matrix is non-invertible?
I am curious about the accepted answer here:Speed up python code for computing matrix cofactors
What would it mean by "This probably means that also for non-invertible matrixes, there is some clever way to calculate the cofactor (i.e., not use the mathematical formula that you use above, but some other equivalent definition)."?
Factorize M = L x D x U, whereL is lower triangular with ones on the main diagonal,U is upper triangular on the main diagonal, andD is diagonal.
You can use back-substitution as with Cholesky factorization, which is similar. Then,
M^{ -1 } = U^{ -1 } x D^{ -1 } x L^{ -1 }
and then transpose the cofactor matrix as :
Cof( M )^T = Det( U ) x Det( D ) x Det( L ) x M^{ -1 }.
If M is singular or nearly so, one element (or more) of D will be zero or nearly zero. Replace those elements with zero in the matrix product and 1 in the determinant, and use the above equation for the transpose cofactor matrix.

Flop count for variable initialization

Consider the following pseudo code:
a <- [0,0,0] (initializing a 3d vector to zeros)
b <- [0,0,0] (initializing a 3d vector to zeros)
c <- a . b (Dot product of two vectors)
In the above pseudo code, what is the flop count (i.e. number floating point operations)?
More generally, what I want to know is whether initialization of variables counts towards the total floating point operations or not, when looking at an algorithm's complexity.
In your case, both a and b vectors are zeros and I don't think that it is a good idea to use zeros to describe or explain the flops operation.
I would say that given vector a with entries a1,a2 and a3, and also given vector b with entries b1, b2, b3. The dot product of the two vectors is equal to aTb that gives
aTb = a1*b1+a2*b2+a3*b3
Here we have 3 multiplication operations
(i.e: a1*b1, a2*b2, a3*b3) and 2 addition operations. In total we have 5 operations or 5 flops.
If we want to generalize this example for n dimensional vectors a_n and b_n, we would have n times multiplication operations and n-1 times addition operations. In total we would end up with n+n-1 = 2n-1 operations or flops.
I hope the example I used above gives you the intuition.

Support Vector Machines

I had these questions in an exam today. State True or False and explain.
If k1(.,.) and k2(.,.) are two valid kernel functions, then if h = k1 - k2, is h(.,.) a valid kernel function?
A standard soft margin SVM is used to classify data set. We have a fixed C parameter. Two different algorithms A1 and A2 are used to obtain the support vector set {S:
α
i > 0}. Call them S1 and S2. Is S1 = S2 in all cases? Assume both algorithm use the same kernel function.
EDITED:
I guessed as:
As kernel function need to be positive semi definite (PSD), the difference between two kernel functions need not be PSD. Hence FALSE.
αi can be different among the two algorithms, the number of support vectors can differ as well. Hence FALSE again.
A) constant 0 is a kernel, constant 1 is a kernel, too. But 0-1=-1 is not PSD.
Thus false IMHO.
B) Assuming 2D data, where x=0 for Class 1, x=1 for Class 2, and y is uniformly random. Any vector from each class is as good a support vector as the others, yielding the same hyperplane. Visually:
x1 | y1
|
x2 | y2
Which SVM is better, the one using x1 and y1 as support vectors, or the one using x2 and y2?

Karatsuba and Toom-3 algorithms for 3-digit number multiplications

I was wondering about this problem concerning Katatsuba's algorithm.
When you apply Karatsuba you basically have to do 3 multiplications per one run of the loop
Those are (let's say ab and cd are 2-digit numbers with digits respectively a, b, c and d):
X = bd
Y = ac
Z = (a+c)(c+d)
and then the sums we were looking for are:
bd = X
ac = Y
(bc + ad) = Z - X - Y
My question is: let's say we have two 3-digit numbers: abc, def. I found out that we will have to perfom only 5 multiplications to do so. I also found this Toom-3 algorithm, but it uses polynomials I can;t quite get. Could someone write down those multiplications and how to calculate the interesting sums bd + ae, ce+ bf, cd + be + af
The basic idea is this: The number 237 is the polynomial p(x)=2x2+3x+7 evaluated at the point x=10. So, we can think of each integer corresponding to a polynomial whose coefficients are the digits of the number. When we evaluate the polynomial at x=10, we get our number back.
What is interesting is that to fully specify a polynomial of degree 2, we need its value at just 3 distinct points. We need 5 values to fully specify a polynomial of degree 4.
So, if we want to multiply two 3 digit numbers, we can do so by:
Evaluating the corresponding polynomials at 5 distinct points.
Multiplying the 5 values. We now have 5 function values of the polynomial of the product.
Finding the coefficients of this polynomial from the five values we computed in step 2.
Karatsuba multiplication works the same way, except that we only need 3 distinct points. Instead of at 10, we evaluate the polynomial at 0, 1, and "infinity", which gives us b,a+b,a and d,d+c,c which multiplied together give you your X,Z,Y.
Now, to write this all out in terms of abc and def is quite involved. In the Wikipedia article, it's actually done quite nicely:
In the Evaluation section, the polynomials are evaluated to give, for example, c,a+b+c,a-b+c,4a+2b+c,a for the first number.
In Pointwise products, the corresponding values for each number are multiplied, which gives:
X = cf
Y = (a+b+c)(d+e+f)
Z = (a+b-c)(d-e+f)
U = (4a+2b+c)(4d+2e+f)
V = ad
In the Interpolation section, these values are combined to give you the digits in the product. This involves solving a 5x5 system of linear equations, so again it's a bit more complicated than the Karatsuba case.