Main Page   Reference Manual   Compound List   File List  

libecc/point.h

Go to the documentation of this file.
00001 //
00009 //
00010 // This file is part of the libecc package.
00011 // Copyright (C) 2003, 2004 by
00012 //
00013 // Carlo Wood, Run on IRC <carlo@alinoe.com>
00014 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
00015 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
00016 //
00017 // This program is free software; you can redistribute it and/or
00018 // modify it under the terms of the GNU General Public License
00019 // as published by the Free Software Foundation; either version 2
00020 // of the License, or (at your option) any later version.
00021 //
00022 // This program is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License
00028 // along with this program; if not, write to the Free Software
00029 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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;        // x coordinate of the point.
00064     polynomial_type M_y;        // y coordinate of the point.
00065     bool M_zero;                // Set when this is the 'point at infinity', in which case M_x and M_y are meaningless.
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);                    // x^2
00145     polynomial_type r((M_x + a) * x2 + b);                      // x^3 + a x^2 + 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);                          // y^2 + x 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 } // namespace libecc
00280 
00281 #endif // LIBECC_POINT_H
Copyright © 2002-2004 Carlo Wood.  All rights reserved.