| 3083 | } |
| 3084 | |
| 3085 | CanonicalForm mulMod (const CanonicalForm& A, const CanonicalForm& B, |
| 3086 | const CFList& MOD) |
| 3087 | { |
| 3088 | if (A.isZero() || B.isZero()) |
| 3089 | return 0; |
| 3090 | |
| 3091 | if (MOD.length() == 1) |
| 3092 | return mulMod2 (A, B, MOD.getLast()); |
| 3093 | |
| 3094 | CanonicalForm M= MOD.getLast(); |
| 3095 | CanonicalForm F= mod (A, M); |
| 3096 | CanonicalForm G= mod (B, M); |
| 3097 | if (F.inCoeffDomain()) |
| 3098 | return G*F; |
| 3099 | if (G.inCoeffDomain()) |
| 3100 | return F*G; |
| 3101 | |
| 3102 | int sizeF= size (F); |
| 3103 | int sizeG= size (G); |
| 3104 | |
| 3105 | if (sizeF / MOD.length() < 100 || sizeG / MOD.length() < 100) |
| 3106 | { |
| 3107 | if (sizeF < sizeG) |
| 3108 | return mod (G*F, MOD); |
| 3109 | else |
| 3110 | return mod (F*G, MOD); |
| 3111 | } |
| 3112 | |
| 3113 | Variable y= M.mvar(); |
| 3114 | int degF= degree (F, y); |
| 3115 | int degG= degree (G, y); |
| 3116 | |
| 3117 | if ((degF <= 1 && F.level() <= M.level()) && |
| 3118 | (degG <= 1 && G.level() <= M.level())) |
| 3119 | { |
| 3120 | CFList buf= MOD; |
| 3121 | buf.removeLast(); |
| 3122 | if (degF == 1 && degG == 1) |
| 3123 | { |
| 3124 | CanonicalForm F0= mod (F, y); |
| 3125 | CanonicalForm F1= div (F, y); |
| 3126 | CanonicalForm G0= mod (G, y); |
| 3127 | CanonicalForm G1= div (G, y); |
| 3128 | if (degree (M) > 2) |
| 3129 | { |
| 3130 | CanonicalForm H00= mulMod (F0, G0, buf); |
| 3131 | CanonicalForm H11= mulMod (F1, G1, buf); |
| 3132 | CanonicalForm H01= mulMod (F0 + F1, G0 + G1, buf); |
| 3133 | return H11*y*y + (H01 - H00 - H11)*y + H00; |
| 3134 | } |
| 3135 | else //here degree (M) == 2 |
| 3136 | { |
| 3137 | buf.append (y); |
| 3138 | CanonicalForm F0G1= mulMod (F0, G1, buf); |
| 3139 | CanonicalForm F1G0= mulMod (F1, G0, buf); |
| 3140 | CanonicalForm F0G0= mulMod (F0, G0, MOD); |
| 3141 | CanonicalForm result= F0G0 + y*(F0G1 + F1G0); |
| 3142 | return result; |
no test coverage detected