00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef LIBECC_POINT_H
00033 #define LIBECC_POINT_H
00034
00035 #include <libecc/polynomial.h>
00036 #include <gmpxx.h>
00037
00038 namespacelibecc {
00039
00040 enum order_algorithm {
00041 order_brute_force,
00042 order_default = order_brute_force
00043 };
00044
00055 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00056 classpoint {
00057 public:
00061 typedef Polynomial polynomial_type;
00062 private:
00063 polynomial_type M_x;
00064 polynomial_type M_y;
00065 bool M_zero;
00066 public:
00070 point(void) : M_zero(true) { }
00076 point(std::string x, std::string y) : M_x(x), M_y(y), M_zero(false) { }
00080 point(polynomial_type const& x, polynomial_type const& y) : M_x(x), M_y(y), M_zero(false) { }
00084 point& operator=(point const& p1);
00088 point& operator+=(point const& p1);
00092 void MULTIPLY_and_assign(point const& pnt, mpz_class const& scalar);
00096 mpz_class order(order_algorithm algorithm = order_default) const;
00102 bool operator==(point const& p1) const;
00108 bool operator!=(point const& p1) const;
00114 bool check(void) const;
00120 polynomial_type const& get_x(void) const{ return M_x; }
00126 polynomial_type const& get_y(void) const{ return M_y; }
00130 bool is_zero(void) const{ return M_zero; }
00134 void print_on(std::ostream& os) const;
00135 };
00136
00137 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00138 bool
00139 point<Polynomial, a, b>::check(void) const
00140 {
00141 if (M_zero)
00142 return true;
00143 bitset_digit_t x2buf[polynomial_type::square_digits];
00144 polynomial_type& x2 = M_x.square(x2buf);
00145 polynomial_type r((M_x + a) * x2 + b);
00146 bitset_digit_t y2buf[polynomial_type::square_digits];
00147 polynomial_type& y2 = M_y.square(y2buf);
00148 polynomial_type l(y2 + M_x * M_y);
00149 return (r == l);
00150 }
00151
00152 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00153 inline bool
00154 point<Polynomial, a, b>::operator!=(point const& p1) const
00155 {
00156 return (M_zero != p1.M_zero || (!M_zero && (M_x != p1.M_x || M_y != p1.M_y)));
00157 }
00158
00159 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00160 inline bool
00161 point<Polynomial, a, b>::operator==(point const& p1) const
00162 {
00163 return !operator!=(p1);
00164 }
00165
00166 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00167 std::ostream&
00168 operator<<(std::ostream& os, point<Polynomial, a, b> const& p1)
00169 {
00170 if (p1.is_zero())
00171 os << "O";
00172 else
00173 os << '(' << p1.get_x() << ", " << p1.get_y() << ')';
00174 return os;
00175 }
00176
00177 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00178 void
00179 point<Polynomial, a, b>::print_on(std::ostream& os) const
00180 {
00181 if (M_zero)
00182 os << "O";
00183 else
00184 os << '(' << M_x << ", " << M_y << ')';
00185 }
00186
00187 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00188 point<Polynomial, a, b>&
00189 point<Polynomial, a, b>::operator=(point<Polynomial, a, b> const& p1)
00190 {
00191 M_zero = p1.M_zero;
00192 if (!M_zero)
00193 {
00194 M_x = p1.M_x;
00195 M_y = p1.M_y;
00196 }
00197 return *this;
00198 }
00199
00200 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00201 void
00202 point<Polynomial, a, b>::MULTIPLY_and_assign(point<Polynomial, a, b> const& pnt, mpz_class const& scalar)
00203 {
00204 M_zero = true;
00205 point tmp(pnt);
00206 unsigned long int p = 0;
00207 size_t end = mpz_sizeinbase(scalar.get_mpz_t(), 2);
00208 for (unsigned long int bit = mpz_scan1(scalar.get_mpz_t(), 0); bit < end; bit = mpz_scan1(scalar.get_mpz_t(), bit + 1))
00209 {
00210 for (; p < bit; ++p)
00211 tmp += tmp;
00212 *this += tmp;
00213 }
00214 }
00215
00216 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00217 point<Polynomial, a, b>&
00218 point<Polynomial, a, b>::operator+=(point<Polynomial, a, b> const& p1)
00219 {
00220 if (!p1.M_zero)
00221 {
00222 if (M_zero)
00223 {
00224 M_x = p1.M_x;
00225 M_y = p1.M_y;
00226 M_zero = false;
00227 }
00228 else if (M_x != p1.M_x)
00229 {
00230 polynomial_type s = M_y + p1.M_y;
00231 s /= M_x + p1.M_x;
00232 bitset_digit_t s2buf[polynomial_type::square_digits];
00233 polynomial_type& new_x = s.square(s2buf);
00234 new_x += s + M_x;
00235 new_x += p1.M_x + a;
00236 M_y += s * (M_x + new_x) + new_x;
00237 M_x = new_x;
00238 }
00239 else if (M_y == p1.M_y && M_x.get_bitset().any())
00240 {
00241 polynomial_type s(M_x + M_y / M_x);
00242 bitset_digit_t s2buf[polynomial_type::square_digits];
00243 polynomial_type& new_x = s.square(s2buf);
00244 new_x += s + a;
00245 bitset_digit_t x2buf[polynomial_type::square_digits];
00246 polynomial_type& x2 = M_x.square(x2buf);
00247 M_y = x2 + new_x * (s + polynomial_type::unity());
00248 M_x = new_x;
00249 }
00250 else
00251 M_zero = true;
00252 }
00253 return *this;
00254 }
00255
00256 template<typename Polynomial, Polynomial const& a, Polynomial const& b>
00257 mpz_class
00258 point<Polynomial, a, b>::order(order_algorithm algorithm) const
00259 {
00260 mpz_class n = 1;
00261 switch(algorithm)
00262 {
00263 case order_brute_force:
00264 {
00265 point nP(*this);
00266 while(!nP.M_zero && nP.M_x.get_bitset().any())
00267 {
00268 nP += *this;
00269 ++n;
00270 }
00271 if (!nP.M_zero)
00272 n += n;
00273 break;
00274 }
00275 }
00276 return n;
00277 }
00278
00279 }
00280
00281 #endif // LIBECC_POINT_H