//Matrix multiplication by a scalar cmatrix scalarmatmul(double complex scalar, cmatrix input){ int i,j; //create output cmatrix returnVal = zeromat(input.rows, input.cols); for(i=0;i<input.rows;i++) for(j=0;j<input.cols;j++) returnVal.entries[i][j] = scalar * input.entries[i][j]; return returnVal; }
//outter product cmatrix outprod(cvector leftvector, cvector rightvector){ int i,j; //create new matrix cmatrix returnVal = zeromat(leftvector.size,rightvector.size); //fill entries for(i=0;i<leftvector.size;i++) for(j=0;j<rightvector.size;j++) returnVal.entries[i][j] = leftvector.entries[i] * conj(rightvector.entries[j]); return returnVal; }
//Matrix addition cmatrix matadd(cmatrix input1, cmatrix input2){ if(input1.rows!=input2.rows || input1.cols!=input2.cols){ fprintf(stderr, "Error in function 'matadd': input1 cols and cols do not match input2 rows and cols\nPossible reasons:\n'input1' and 'input2' cannot be added because they are not the same size\n"); exit(1); } int i,j; //create output cmatrix returnVal = zeromat(input1.rows, input1.cols); for(i=0;i<input1.rows;i++) for(j=0;j<input1.cols;j++) returnVal.entries[i][j] = input1.entries[i][j] + input2.entries[i][j]; return returnVal; }
void eyemat(double *mat) /* ======== Return 3x3 Identity Matrix ========= */ { zeromat(mat); mat[0]=1; mat[4]=1; mat[8]=1; }
//Matrix multiplication cmatrix matmul(cmatrix leftmatrix, cmatrix rightmatrix){ if(leftmatrix.cols!=rightmatrix.rows){ fprintf(stderr, "Error in function 'matmul': leftmatrix cols and rightmatrix rows do not match\nPossible reasons:\n'leftmatrix' and 'rightmatrix' cannot be multiplied\n"); exit(1); } int i,j,k; //create output cmatrix returnVal = zeromat(leftmatrix.rows, rightmatrix.cols); for(i=0;i<leftmatrix.rows;i++) for(j=0;j<rightmatrix.cols;j++) { for(k=0;k<leftmatrix.cols;k++) returnVal.entries[i][j]+=rightmatrix.entries[i][k]*leftmatrix.entries[k][j]; } return returnVal; }
//Matrix transpose cmatrix transpose(cmatrix input){ cmatrix returnVal = zeromat(input.cols, input.rows); for(int i=0;i<input.rows;i++) for(int j=0;j<input.cols;j++) returnVal.entries[j][i]=input.entries[i][j]; return returnVal; }
void blochsim(double *b1real, double *b1imag, double *xgrad, double *ygrad, double *zgrad, double *tsteps, int ntime, double *e1, double *e2, double df, double dx, double dy, double dz, double *mx, double *my, double *mz, int mode) /* Go through time for one df and one dx,dy,dz. */ { int tcount; double gammadx; double gammady; double gammadz; double rotmat[9]; double amat[9], bvec[3]; /* A and B propagation matrix and vector */ double arot[9], brot[3]; /* A and B after rotation step. */ double decmat[9]; /* Decay matrix for each time step. */ double decvec[3]; /* Recovery vector for each time step. */ double rotx,roty,rotz; /* Rotation axis coordinates. */ double imat[9], mvec[3]; double mcurr0[3]; /* Current magnetization before rotation. */ double mcurr1[3]; /* Current magnetization before decay. */ eyemat(amat); /* A is the identity matrix. */ eyemat(imat); /* I is the identity matrix. */ zerovec(bvec); zerovec(decvec); zeromat(decmat); gammadx = dx*GAMMA; /* Convert to Hz/cm */ gammady = dy*GAMMA; /* Convert to Hz/cm */ gammadz = dz*GAMMA; /* Convert to Hz/cm */ mcurr0[0] = *mx; /* Set starting x magnetization */ mcurr0[1] = *my; /* Set starting y magnetization */ mcurr0[2] = *mz; /* Set starting z magnetization */ for (tcount = 0; tcount < ntime; tcount++) { /* Rotation */ rotz = -(*xgrad++ * gammadx + *ygrad++ * gammady + *zgrad++ * gammadz + df*TWOPI ) * *tsteps; rotx = (- *b1real++ * GAMMA * *tsteps); roty = (+ *b1imag++ * GAMMA * *tsteps++); calcrotmat(rotx, roty, rotz, rotmat); if (mode == 1) { multmats(rotmat,amat,arot); multmatvec(rotmat,bvec,brot); } else multmatvec(rotmat,mcurr0,mcurr1); /* Decay */ decvec[2]= 1- *e1; decmat[0]= *e2; decmat[4]= *e2++; decmat[8]= *e1++; if (mode == 1) { multmats(decmat,arot,amat); multmatvec(decmat,brot,bvec); addvecs(bvec,decvec,bvec); } else { multmatvec(decmat,mcurr1,mcurr0); addvecs(mcurr0,decvec,mcurr0); } /* printf("rotmat = [%6.3f %6.3f %6.3f ] \n",rotmat[0],rotmat[3], rotmat[6]); printf(" [%6.3f %6.3f %6.3f ] \n",rotmat[1],rotmat[4], rotmat[7]); printf(" [%6.3f %6.3f %6.3f ] \n",rotmat[2],rotmat[5], rotmat[8]); printf("A = [%6.3f %6.3f %6.3f ] \n",amat[0],amat[3],amat[6]); printf(" [%6.3f %6.3f %6.3f ] \n",amat[1],amat[4],amat[7]); printf(" [%6.3f %6.3f %6.3f ] \n",amat[2],amat[5],amat[8]); printf(" B = <%6.3f,%6.3f,%6.3f> \n",bvec[0],bvec[1],bvec[2]); printf("<mx,my,mz> = <%6.3f,%6.3f,%6.3f> \n", amat[6] + bvec[0], amat[7] + bvec[1], amat[8] + bvec[2]); printf("\n"); */ if (mode == 2) /* Sample output at times. */ /* Only do this if transient! */ { *mx = mcurr0[0]; *my = mcurr0[1]; *mz = mcurr0[2]; mx++; my++; mz++; } } /* If only recording the endpoint, either store the last point, or calculate the steady-state endpoint. */ if (mode==0) /* Indicates start at given m, or m0. */ { *mx = mcurr0[0]; *my = mcurr0[1]; *mz = mcurr0[2]; } else if (mode==1) /* Indicates to find steady-state magnetization */ { scalemat(amat,-1.0); /* Negate A matrix */ addmats(amat,imat,amat); /* Now amat = (I-A) */ invmat(amat,imat); /* Reuse imat as inv(I-A) */ multmatvec(imat,bvec,mvec); /* Now M = inv(I-A)*B */ *mx = mvec[0]; *my = mvec[1]; *mz = mvec[2]; } }
static GEN nf_LLL_cmbf(nfcmbf_t *T, GEN p, long k, long rec) { nflift_t *L = T->L; GEN pk = L->pk, PRK = L->prk, PRKinv = L->iprk, GSmin = L->GSmin; GEN Tpk = L->Tpk; GEN famod = T->fact, nf = T->nf, ZC = T->ZC, Br = T->Br; GEN Pbase = T->polbase, P = T->pol, dn = T->dn; GEN nfT = gel(nf,1); GEN Btra; long dnf = degpol(nfT), dP = degpol(P); double BitPerFactor = 0.5; /* nb bits / modular factor */ long i, C, tmax, n0; GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO; double Bhigh; pari_sp av, av2, lim; long ti_LLL = 0, ti_CF = 0; pari_timer ti2, TI; lP = absi(leading_term(P)); if (is_pm1(lP)) lP = NULL; n0 = lg(famod) - 1; /* Lattice: (S PRK), small vector (vS vP). To find k bound for the image, * write S = S1 q + S0, P = P1 q + P0 * |S1 vS + P1 vP|^2 <= Bhigh for all (vS,vP) assoc. to true factors */ Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2, dnf))); Bhigh = get_Bhigh(n0, dnf); C = (long)ceil(sqrt(Bhigh/n0)) + 1; /* C^2 n0 ~ Bhigh */ Bnorm = dbltor( n0 * C * C + Bhigh ); ZERO = zeromat(n0, dnf); av = avma; lim = stack_lim(av, 1); TT = cgetg(n0+1, t_VEC); Tra = cgetg(n0+1, t_MAT); for (i=1; i<=n0; i++) TT[i] = 0; CM_L = gscalsmat(C, n0); /* tmax = current number of traces used (and computed so far) */ for(tmax = 0;; tmax++) { long a, b, bmin, bgood, delta, tnew = tmax + 1, r = lg(CM_L)-1; GEN oldCM_L, M_L, q, S1, P1, VV; int first = 1; /* bound for f . S_k(genuine factor) = ZC * bound for T_2(S_tnew) */ Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2*tnew, dnf))); bmin = logint(ceil_safe(sqrtr(Btra)), gen_2, NULL); if (DEBUGLEVEL>2) fprintferr("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n", r, tmax, bmin); /* compute Newton sums (possibly relifting first) */ if (gcmp(GSmin, Btra) < 0) { nflift_t L1; GEN polred; bestlift_init(k<<1, nf, T->pr, Btra, &L1); polred = ZqX_normalize(Pbase, lP, &L1); k = L1.k; pk = L1.pk; PRK = L1.prk; PRKinv = L1.iprk; GSmin = L1.GSmin; Tpk = L1.Tpk; famod = hensel_lift_fact(polred, famod, Tpk, p, pk, k); for (i=1; i<=n0; i++) TT[i] = 0; } for (i=1; i<=n0; i++) { GEN h, lPpow = lP? gpowgs(lP, tnew): NULL; GEN z = polsym_gen(gel(famod,i), gel(TT,i), tnew, Tpk, pk); gel(TT,i) = z; h = gel(z,tnew+1); /* make Newton sums integral */ lPpow = mul_content(lPpow, dn); if (lPpow) h = FpX_red(gmul(h,lPpow), pk); gel(Tra,i) = nf_bestlift(h, NULL, L); /* S_tnew(famod) */ } /* compute truncation parameter */ if (DEBUGLEVEL>2) { TIMERstart(&ti2); TIMERstart(&TI); } oldCM_L = CM_L; av2 = avma; b = delta = 0; /* -Wall */ AGAIN: M_L = Q_div_to_int(CM_L, utoipos(C)); VV = get_V(Tra, M_L, PRK, PRKinv, pk, &a); if (first) { /* initialize lattice, using few p-adic digits for traces */ bgood = (long)(a - max(32, BitPerFactor * r)); b = max(bmin, bgood); delta = a - b; } else { /* add more p-adic digits and continue reduction */ if (a < b) b = a; b = max(b-delta, bmin); if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */ } /* restart with truncated entries */ q = int2n(b); P1 = gdivround(PRK, q); S1 = gdivround(Tra, q); T2 = gsub(gmul(S1, M_L), gmul(P1, VV)); m = vconcat( CM_L, T2 ); if (first) { first = 0; m = shallowconcat( m, vconcat(ZERO, P1) ); /* [ C M_L 0 ] * m = [ ] square matrix * [ T2' PRK ] T2' = Tra * M_L truncated */ } CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL); if (DEBUGLEVEL>2) fprintferr("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n", a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, TIMER(&TI)); if (!CM_L) { list = mkcol(QXQX_normalize(P,nfT)); break; } if (b > bmin) { CM_L = gerepilecopy(av2, CM_L); goto AGAIN; } if (DEBUGLEVEL>2) msgTIMER(&ti2, "for this trace"); i = lg(CM_L) - 1; if (i == r && gequal(CM_L, oldCM_L)) { CM_L = oldCM_L; avma = av2; continue; } if (i <= r && i*rec < n0) { pari_timer ti; if (DEBUGLEVEL>2) TIMERstart(&ti); list = nf_chk_factors(T, P, Q_div_to_int(CM_L,utoipos(C)), famod, pk); if (DEBUGLEVEL>2) ti_CF += TIMER(&ti); if (list) break; CM_L = gerepilecopy(av2, CM_L); } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"nf_LLL_cmbf"); gerepileall(av, Tpk? 9: 8, &CM_L,&TT,&Tra,&famod,&pk,&GSmin,&PRK,&PRKinv,&Tpk); } } if (DEBUGLEVEL>2) fprintferr("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF); return list; }