You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@milagro.apache.org by km...@apache.org on 2020/05/05 06:39:19 UTC

[incubator-milagro-crypto-rust] 33/44: Remove unecessary copying

This is an automated email from the ASF dual-hosted git repository.

kmccusker pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-crypto-rust.git

commit 0707ae6422c101a1113610112725419f4688964e
Author: Kirk Baird <ba...@outlook.com>
AuthorDate: Mon Apr 20 22:13:46 2020 +1000

    Remove unecessary copying
    
    Signed-off-by: Kirk Baird <ba...@outlook.com>
---
 src/big.rs     |  91 +++------
 src/bls.rs     |   6 +-
 src/bls256.rs  |   6 +-
 src/dbig.rs    |  33 +--
 src/ecdh.rs    |  34 ++--
 src/ecp.rs     | 417 +++++++++++++++++---------------------
 src/ecp2.rs    | 231 ++++++++++-----------
 src/ecp4.rs    | 272 ++++++++++++-------------
 src/ecp8.rs    | 440 +++++++++++++++++++---------------------
 src/ff.rs      |  55 ++---
 src/fp.rs      | 134 ++++++------
 src/fp12.rs    | 448 ++++++++++++++++++----------------------
 src/fp16.rs    | 273 +++++++++++--------------
 src/fp2.rs     | 131 +++++-------
 src/fp24.rs    | 510 +++++++++++++++++++++-------------------------
 src/fp4.rs     | 308 +++++++++++++---------------
 src/fp48.rs    | 630 +++++++++++++++++++++++++++------------------------------
 src/fp8.rs     | 303 +++++++++++++--------------
 src/mpin.rs    |  23 +--
 src/mpin192.rs |  21 +-
 src/mpin256.rs |  21 +-
 src/nhs.rs     |   1 -
 src/pair.rs    | 284 +++++++++++---------------
 src/pair192.rs | 250 ++++++++++-------------
 src/pair256.rs | 322 ++++++++++++-----------------
 src/rsa.rs     |  10 +-
 26 files changed, 2340 insertions(+), 2914 deletions(-)

diff --git a/src/big.rs b/src/big.rs
index e4eca10..f0696c7 100644
--- a/src/big.rs
+++ b/src/big.rs
@@ -38,17 +38,11 @@ pub const HMASK: Chunk = (1 << HBITS) - 1;
 pub const NEXCESS: isize = 1 << (arch::CHUNK - BASEBITS - 1);
 pub const BIGBITS: usize = MODBYTES * 8;
 
-#[derive(Copy)]
+#[derive(Clone)]
 pub struct Big {
     pub w: [Chunk; NLEN],
 }
 
-impl Clone for Big {
-    fn clone(&self) -> Big {
-        *self
-    }
-}
-
 impl fmt::Display for Big {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "Big: [ {} ]", self.tostring())
@@ -109,15 +103,6 @@ impl Big {
         s
     }
 
-    /// Creates a copy of the Big
-    pub fn new_copy(y: &Big) -> Big {
-        let mut s = Big::new();
-        for i in 0..NLEN {
-            s.w[i] = y.w[i]
-        }
-        s
-    }
-
     pub fn new_dcopy(y: &DBig) -> Big {
         let mut s = Big::new();
         for i in 0..NLEN {
@@ -180,13 +165,6 @@ impl Big {
         }
     }
 
-    /// Copy from another Big
-    pub fn copy(&mut self, x: &Big) {
-        for i in 0..NLEN {
-            self.w[i] = x.w[i]
-        }
-    }
-
     /// Copy from a DBig
     pub fn dcopy(&mut self, x: &DBig) {
         for i in 0..NLEN {
@@ -289,7 +267,7 @@ impl Big {
     /// Return number of bits
     pub fn nbits(&self) -> usize {
         let mut k = NLEN - 1;
-        let mut s = Big::new_copy(&self);
+        let mut s = self.clone();
         s.norm();
         while (k as isize) >= 0 && s.w[k] == 0 {
             k = k.wrapping_sub(1)
@@ -323,7 +301,7 @@ impl Big {
         }
 
         for i in (0..len).rev() {
-            let mut b = Big::new_copy(&self);
+            let mut b = self.clone();
             b.shr(i * 4);
             s = s + &format!("{:X}", b.w[0] & 15);
         }
@@ -422,7 +400,7 @@ impl Big {
     ///
     /// Convert this Big to byte array from index `n`
     pub fn tobytearray(&self, b: &mut [u8], n: usize) {
-        let mut c = Big::new_copy(self);
+        let mut c = self.clone();
         c.norm();
 
         for i in (0..(MODBYTES as usize)).rev() {
@@ -599,19 +577,16 @@ impl Big {
     /// a = 1/a mod 2^256. This is very fast!
     pub fn invmod2m(&mut self) {
         let mut u = Big::new();
-        let mut b = Big::new();
-        let mut c = Big::new();
-
         u.inc(Big::invmod256(self.lastbits(8)));
 
         let mut i = 8;
         while i < BIGBITS {
             u.norm();
-            b.copy(self);
+            let mut b = self.clone();
             b.mod2m(i);
             let mut t1 = Big::smul(&u, &b);
             t1.shr(i);
-            c.copy(self);
+            let mut c = self.clone();
             c.shr(i);
             c.mod2m(i);
 
@@ -620,7 +595,7 @@ impl Big {
             t1.add(&t2);
             t1.norm();
             b = Big::smul(&t1, &u);
-            t1.copy(&b);
+            t1 = b.clone();
             t1.mod2m(i);
 
             t2.one();
@@ -632,7 +607,7 @@ impl Big {
             i <<= 1;
         }
         u.mod2m(BIGBITS);
-        self.copy(&u);
+        *self = u;
         self.norm();
     }
 
@@ -641,7 +616,7 @@ impl Big {
     /// reduce self mod m
     pub fn rmod(&mut self, n: &Big) {
         let mut k = 0;
-        let mut m = Big::new_copy(n);
+        let mut m = n.clone();
         let mut r = Big::new();
         self.norm();
         if Big::comp(self, &m) < 0 {
@@ -658,7 +633,7 @@ impl Big {
         while k > 0 {
             m.fshr(1);
 
-            r.copy(self);
+            r = self.clone();
             r.sub(&m);
             r.norm();
             self.cmove(
@@ -676,8 +651,8 @@ impl Big {
         let mut k = 0;
         self.norm();
         let mut e = Big::new_int(1);
-        let mut b = Big::new_copy(self);
-        let mut m = Big::new_copy(n);
+        let mut b = self.clone();
+        let mut m = n.clone();
         let mut r = Big::new();
         self.zero();
 
@@ -691,12 +666,12 @@ impl Big {
             m.fshr(1);
             e.fshr(1);
 
-            r.copy(&b);
+            r = b.clone();
             r.sub(&m);
             r.norm();
             let d = (1 - ((r.w[NLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize;
             b.cmove(&r, d);
-            r.copy(self);
+            r = self.clone();
             r.add(&e);
             r.norm();
             self.cmove(&r, d);
@@ -736,7 +711,7 @@ impl Big {
         let mut d = DBig::new();
         let mut j = 0;
         let mut r: u8 = 0;
-        let t = Big::new_copy(q);
+        let t = q.clone();
         for _ in 0..2 * t.nbits() {
             if j == 0 {
                 r = rng.getbyte();
@@ -767,8 +742,8 @@ impl Big {
         }
         self.norm();
 
-        x.copy(self);
-        n.copy(p);
+        x = self.clone();
+        n = p.clone();
         x.rmod(p);
 
         while Big::comp(&n, &one) > 0 {
@@ -785,10 +760,10 @@ impl Big {
                 m += (n8 * n8 - 1) / 8
             }
             m += (n8 - 1) * ((x.lastbits(2) as usize) - 1) / 4;
-            t.copy(&n);
+            t = n.clone();
             t.rmod(&x);
-            n.copy(&x);
-            x.copy(&t);
+            n = x.clone();
+            x = t.clone();
             m %= 2;
         }
         if m == 0 {
@@ -802,8 +777,8 @@ impl Big {
     /// self = 1/self mod p. Binary method
     pub fn invmodp(&mut self, p: &Big) {
         self.rmod(p);
-        let mut u = Big::new_copy(self);
-        let mut v = Big::new_copy(p);
+        let mut u = self.clone();
+        let mut v = p.clone();
         let mut x1 = Big::new_int(1);
         let mut x2 = Big::new();
         let mut t = Big::new();
@@ -832,7 +807,7 @@ impl Big {
                 if Big::comp(&x1, &x2) >= 0 {
                     x1.sub(&x2)
                 } else {
-                    t.copy(p);
+                    t = p.clone();
                     t.sub(&x2);
                     x1.add(&t);
                 }
@@ -843,7 +818,7 @@ impl Big {
                 if Big::comp(&x2, &x1) >= 0 {
                     x2.sub(&x1)
                 } else {
-                    t.copy(p);
+                    t = p.clone();
                     t.sub(&x1);
                     x2.add(&t);
                 }
@@ -851,9 +826,9 @@ impl Big {
             }
         }
         if Big::comp(&u, &one) == 0 {
-            self.copy(&x1)
+            *self = x1
         } else {
-            self.copy(&x2)
+            *self = x2
         }
     }
 
@@ -1038,8 +1013,8 @@ impl Big {
     ///
     /// return a*b mod m
     pub fn modmul(a1: &Big, b1: &Big, m: &Big) -> Big {
-        let mut a = Big::new_copy(a1);
-        let mut b = Big::new_copy(b1);
+        let mut a = a1.clone();
+        let mut b = b1.clone();
         a.rmod(m);
         b.rmod(m);
         let mut d = Big::mul(&a, &b);
@@ -1048,7 +1023,7 @@ impl Big {
 
     /// return a^2 mod m
     pub fn modsqr(a1: &Big, m: &Big) -> Big {
-        let mut a = Big::new_copy(a1);
+        let mut a = a1.clone();
         a.rmod(m);
         let mut d = Big::sqr(&a);
         d.dmod(m)
@@ -1058,7 +1033,7 @@ impl Big {
     ///
     /// return -a mod m
     pub fn modneg(a1: &Big, m: &Big) -> Big {
-        let mut a = Big::new_copy(a1);
+        let mut a = a1.clone();
         a.rmod(m);
         m.minus(&a)
     }
@@ -1068,11 +1043,11 @@ impl Big {
     /// return this^e mod m
     pub fn powmod(&mut self, e1: &Big, m: &Big) -> Big {
         self.norm();
-        let mut e = Big::new_copy(e1);
+        let mut e = e1.clone();
         e.norm();
         let mut a = Big::new_int(1);
-        let mut z = Big::new_copy(&e);
-        let mut s = Big::new_copy(self);
+        let mut z = e.clone();
+        let mut s = self.clone();
         loop {
             let bt = z.parity();
             z.fshr(1);
diff --git a/src/bls.rs b/src/bls.rs
index 1bc71cb..c956441 100644
--- a/src/bls.rs
+++ b/src/bls.rs
@@ -17,13 +17,13 @@ specific language governing permissions and limitations
 under the License.
 */
 
-use super::ecp::ECP;
-use super::ecp2::ECP2;
-use std::str;
 use super::big;
 use super::big::Big;
+use super::ecp::ECP;
+use super::ecp2::ECP2;
 use super::pair;
 use super::rom;
+use std::str;
 
 use rand::RAND;
 use sha3::SHA3;
diff --git a/src/bls256.rs b/src/bls256.rs
index 11fb5a1..785ad2d 100644
--- a/src/bls256.rs
+++ b/src/bls256.rs
@@ -17,13 +17,13 @@ specific language governing permissions and limitations
 under the License.
 */
 
-use super::ecp::ECP;
-use super::ecp8::ECP8;
-use std::str;
 use super::big;
 use super::big::Big;
+use super::ecp::ECP;
+use super::ecp8::ECP8;
 use super::pair256;
 use super::rom;
+use std::str;
 
 use rand::RAND;
 use sha3::SHA3;
diff --git a/src/dbig.rs b/src/dbig.rs
index 2479637..689aeb8 100644
--- a/src/dbig.rs
+++ b/src/dbig.rs
@@ -22,17 +22,11 @@ use super::super::arch::Chunk;
 use super::big;
 use super::big::Big;
 
-#[derive(Copy)]
+#[derive(Clone)]
 pub struct DBig {
     pub w: [Chunk; big::DNLEN],
 }
 
-impl Clone for DBig {
-    fn clone(&self) -> DBig {
-        *self
-    }
-}
-
 impl DBig {
     pub fn new() -> DBig {
         DBig {
@@ -40,14 +34,6 @@ impl DBig {
         }
     }
 
-    pub fn new_copy(y: &DBig) -> DBig {
-        let mut s = DBig::new();
-        for i in 0..big::DNLEN {
-            s.w[i] = y.w[i]
-        }
-        s
-    }
-
     pub fn new_scopy(x: &Big) -> DBig {
         let mut b = DBig::new();
         for i in 0..big::NLEN {
@@ -108,13 +94,6 @@ impl DBig {
         }
     }
 
-    /// Copy from another DBig
-    pub fn copy(&mut self, x: &DBig) {
-        for i in 0..big::DNLEN {
-            self.w[i] = x.w[i];
-        }
-    }
-
     /// Copy from a Big
     pub fn ucopy(&mut self, x: &Big) {
         for i in 0..big::NLEN {
@@ -202,7 +181,7 @@ impl DBig {
         while k > 0 {
             m.shr(1);
 
-            dr.copy(self);
+            dr = self.clone();
             dr.sub(&m);
             dr.norm();
             self.cmove(
@@ -236,12 +215,12 @@ impl DBig {
             m.shr(1);
             e.shr(1);
 
-            dr.copy(self);
+            dr = self.clone();
             dr.sub(&m);
             dr.norm();
             let d = (1 - ((dr.w[big::DNLEN - 1] >> (arch::CHUNK - 1)) & 1)) as isize;
             self.cmove(&dr, d);
-            r.copy(&a);
+            r = a.clone();
             r.add(&e);
             r.norm();
             a.cmove(&r, d);
@@ -265,7 +244,7 @@ impl DBig {
     /// Return number of bits
     pub fn nbits(&self) -> usize {
         let mut k = big::DNLEN - 1;
-        let mut s = DBig::new_copy(&self);
+        let mut s = self.clone();
         s.norm();
         while (k as isize) >= 0 && s.w[k] == 0 {
             k = k.wrapping_sub(1)
@@ -295,7 +274,7 @@ impl DBig {
         }
 
         for i in (0..len).rev() {
-            let mut b = DBig::new_copy(&self);
+            let mut b = self.clone();
             b.shr(i * 4);
             s = s + &format!("{:X}", b.w[0] & 15);
         }
diff --git a/src/ecdh.rs b/src/ecdh.rs
index 934ea82..0772ee7 100644
--- a/src/ecdh.rs
+++ b/src/ecdh.rs
@@ -226,7 +226,7 @@ pub fn pbkdf2(sha: usize, pass: &[u8], salt: &[u8], rep: usize, olen: usize, k:
 /// Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag)
 pub fn hmac(sha: usize, m: &[u8], k: &[u8], olen: usize, tag: &mut [u8]) -> bool {
     // Input is from an octet m
-	// olen is requested output length in bytes. k is the key
+    // olen is requested output length in bytes. k is the key
     // The output is the calculated tag
     let mut b: [u8; 64] = [0; 64]; // Not good
     let mut k0: [u8; 128] = [0; 128];
@@ -505,34 +505,32 @@ pub fn ecpsp_dsa(
 
     let mut cb = Big::new();
     let mut db = Big::new();
-    let mut tb = Big::new();
-    let mut V = ECP::new();
 
     while db.iszilch() {
         let mut u = Big::randomnum(&r, rng);
         let w = Big::randomnum(&r, rng); // side channel masking
 
-        V.copy(&G);
+        let mut V = G.clone();
         V = V.mul(&u);
         let vx = V.getx();
-        cb.copy(&vx);
+        cb = vx.clone();
         cb.rmod(&r);
         if cb.iszilch() {
             continue;
         }
 
-        tb.copy(&Big::modmul(&u, &w, &r));
-        u.copy(&tb);
+        let mut tb = Big::modmul(&u, &w, &r);
+        u = tb.clone();
 
         u.invmodp(&r);
-        db.copy(&Big::modmul(&sc, &cb, &r));
+        db = Big::modmul(&sc, &cb, &r);
         db.add(&fb);
 
-        tb.copy(&Big::modmul(&db, &w, &r));
-        db.copy(&tb);
+        tb = Big::modmul(&db, &w, &r);
+        db = tb.clone();
 
-        tb.copy(&Big::modmul(&u, &db, &r));
-        db.copy(&tb);
+        tb = Big::modmul(&u, &db, &r);
+        db = tb.clone();
     }
 
     cb.tobytes(&mut t);
@@ -556,30 +554,27 @@ pub fn ecpvp_dsa(sha: usize, w: &[u8], f: &[u8], c: &[u8], d: &[u8]) -> isize {
     hashit(sha, f, 0, None, big::MODBYTES as usize, &mut b);
 
     let G = ECP::generator();
-
     let r = Big::new_ints(&rom::CURVE_ORDER);
 
     let cb = Big::frombytes(c); // c or &c ?
     let mut db = Big::frombytes(d); // d or &d ?
-    let mut fb = Big::frombytes(&b);
-    let mut tb = Big::new();
 
     if cb.iszilch() || Big::comp(&cb, &r) >= 0 || db.iszilch() || Big::comp(&db, &r) >= 0 {
         res = INVALID;
     }
 
     if res == 0 {
+        let mut fb = Big::frombytes(&b);
         db.invmodp(&r);
-        tb.copy(&Big::modmul(&fb, &db, &r));
-        fb.copy(&tb);
+        let tb = Big::modmul(&fb, &db, &r);
+        fb = tb.clone();
         let h2 = Big::modmul(&cb, &db, &r);
 
         let WP = ECP::frombytes(&w);
         if WP.is_infinity() {
             res = ERROR;
         } else {
-            let mut P = ECP::new();
-            P.copy(&WP);
+            let mut P = WP.clone();
 
             P = P.mul2(&h2, &G, &fb);
 
@@ -754,7 +749,6 @@ mod tests {
 
     #[test]
     fn test_ecdh() {
-
         let mut rng = create_rng();
 
         let pw = "M0ng00se";
diff --git a/src/ecp.rs b/src/ecp.rs
index 07e19be..2c9b9db 100644
--- a/src/ecp.rs
+++ b/src/ecp.rs
@@ -27,7 +27,7 @@ use std::fmt;
 use std::str::SplitWhitespace;
 pub use types::CurveType;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct ECP {
     x: FP,
     y: FP,
@@ -83,7 +83,7 @@ impl ECP {
                 E.inf();
             }
         } else {
-            let mut y2 = FP::new_copy(&E.y);
+            let mut y2 = E.y.clone();
             y2.sqr();
             if !y2.equals(&rhs) {
                 E.inf();
@@ -106,11 +106,11 @@ impl ECP {
             if ny.redc().parity() != s {
                 ny.neg()
             }
-            E.y.copy(&ny);
+            E.y = ny;
         } else {
             E.inf()
         }
-        return E;
+        E
     }
 
     #[allow(non_snake_case)]
@@ -123,7 +123,7 @@ impl ECP {
         let mut rhs = ECP::rhs(&E.x);
         if rhs.jacobi() == 1 {
             if CURVETYPE != CurveType::Montgomery {
-                E.y.copy(&rhs.sqrt())
+                E.y = rhs.sqrt()
             }
         } else {
             E.inf();
@@ -146,15 +146,15 @@ impl ECP {
 
     /* Calculate RHS of curve equation */
     fn rhs(x: &FP) -> FP {
-        let mut r = FP::new_copy(x);
+        let mut r = x.clone();
         r.sqr();
 
         if CURVETYPE == CurveType::Weierstrass {
             // x^3+Ax+B
-            let b = FP::new_big(&Big::new_ints(&rom::CURVE_B));
+            let b = FP::new_big(Big::new_ints(&rom::CURVE_B));
             r.mul(x);
             if rom::CURVE_A == -3 {
-                let mut cx = FP::new_copy(x);
+                let mut cx = x.clone();
                 cx.imul(3);
                 cx.neg();
                 cx.norm();
@@ -164,7 +164,7 @@ impl ECP {
         }
         if CURVETYPE == CurveType::Edwards {
             // (Ax^2-1)/(Bx^2-1)
-            let mut b = FP::new_big(&Big::new_ints(&rom::CURVE_B));
+            let mut b = FP::new_big(Big::new_ints(&rom::CURVE_B));
             let one = FP::new_int(1);
             b.mul(&r);
             b.sub(&one);
@@ -179,8 +179,7 @@ impl ECP {
         }
         if CURVETYPE == CurveType::Montgomery {
             // x^3+Ax^2+x
-            let mut x3 = FP::new();
-            x3.copy(&r);
+            let mut x3 = r.clone();
             x3.mul(x);
             r.imul(rom::CURVE_A);
             r.add(&x3);
@@ -224,15 +223,6 @@ impl ECP {
         return ((x >> 31) & 1) as isize;
     }
 
-    /* this=P */
-    pub fn copy(&mut self, P: &ECP) {
-        self.x.copy(&P.x);
-        if CURVETYPE != CurveType::Montgomery {
-            self.y.copy(&P.y)
-        }
-        self.z.copy(&P.z);
-    }
-
     /* this=-this */
     pub fn neg(&mut self) {
         if CURVETYPE == CurveType::Weierstrass {
@@ -252,8 +242,6 @@ impl ECP {
 
     /* Constant time select from pre-computed table */
     fn selector(&mut self, W: &[ECP], b: i32) {
-        // unsure about &[& syntax. An array of pointers I hope..
-        let mut MP = ECP::new();
         let m = b >> 31;
         let mut babs = (b ^ m) - m;
 
@@ -268,26 +256,24 @@ impl ECP {
         self.cmove(&W[6], ECP::teq(babs, 6));
         self.cmove(&W[7], ECP::teq(babs, 7));
 
-        MP.copy(self);
+        let mut MP = self.clone();
         MP.neg();
         self.cmove(&MP, (m & 1) as isize);
     }
 
     /* Test P == Q */
     pub fn equals(&self, Q: &ECP) -> bool {
-        let mut a = FP::new();
-        let mut b = FP::new();
-        a.copy(&self.x);
+        let mut a = self.getpx();
         a.mul(&Q.z);
-        b.copy(&Q.x);
+        let mut b = Q.getpx();
         b.mul(&self.z);
         if !a.equals(&b) {
             return false;
         }
         if CURVETYPE != CurveType::Montgomery {
-            a.copy(&self.y);
+            a = self.getpy();
             a.mul(&Q.z);
-            b.copy(&Q.y);
+            b = Q.getpy();
             b.mul(&self.z);
             if !a.equals(&b) {
                 return false;
@@ -313,21 +299,19 @@ impl ECP {
             self.y.mul(&self.z);
             self.y.reduce();
         }
-        self.z.copy(&one);
+        self.z = one;
     }
 
     /* extract x as a Big */
     pub fn getx(&self) -> Big {
-        let mut W = ECP::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
         return W.x.redc();
     }
 
     /* extract y as a Big */
     pub fn gety(&self) -> Big {
-        let mut W = ECP::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
         return W.y.redc();
     }
@@ -340,27 +324,23 @@ impl ECP {
 
     /* extract x as an FP */
     pub fn getpx(&self) -> FP {
-        let w = FP::new_copy(&self.x);
-        return w;
+        self.x.clone()
     }
     /* extract y as an FP */
     pub fn getpy(&self) -> FP {
-        let w = FP::new_copy(&self.y);
-        return w;
+        self.y.clone()
     }
 
     /* extract z as an FP */
     pub fn getpz(&self) -> FP {
-        let w = FP::new_copy(&self.z);
-        return w;
+        self.z.clone()
     }
 
     /* convert to byte array */
     pub fn tobytes(&self, b: &mut [u8], compress: bool) {
         let mb = big::MODBYTES as usize;
         let mut t: [u8; big::MODBYTES as usize] = [0; big::MODBYTES as usize];
-        let mut W = ECP::new();
-        W.copy(self);
+        let mut W = self.clone();
 
         W.affine();
         W.x.redc().tobytes(&mut t);
@@ -427,8 +407,7 @@ impl ECP {
 
     /* convert to hex string */
     pub fn tostring(&self) -> String {
-        let mut W = ECP::new();
-        W.copy(self);
+        let W = self.clone();
         if W.is_infinity() {
             return String::from("infinity");
         }
@@ -465,14 +444,14 @@ impl ECP {
     pub fn dbl(&mut self) {
         if CURVETYPE == CurveType::Weierstrass {
             if rom::CURVE_A == 0 {
-                let mut t0 = FP::new_copy(&self.y);
+                let mut t0 = self.y.clone();
                 t0.sqr();
-                let mut t1 = FP::new_copy(&self.y);
+                let mut t1 = self.y.clone();
                 t1.mul(&self.z);
-                let mut t2 = FP::new_copy(&self.z);
+                let mut t2 = self.z.clone();
                 t2.sqr();
 
-                self.z.copy(&t0);
+                self.z = t0.clone();
                 self.z.add(&t0);
                 self.z.norm();
                 self.z.dbl();
@@ -480,41 +459,39 @@ impl ECP {
                 self.z.norm();
                 t2.imul(3 * rom::CURVE_B_I);
 
-                let mut x3 = FP::new_copy(&t2);
+                let mut x3 = t2.clone();
                 x3.mul(&self.z);
 
-                let mut y3 = FP::new_copy(&t0);
+                let mut y3 = t0.clone();
                 y3.add(&t2);
                 y3.norm();
                 self.z.mul(&t1);
-                t1.copy(&t2);
+                t1 = t2.clone();
                 t1.add(&t2);
                 t2.add(&t1);
                 t0.sub(&t2);
                 t0.norm();
                 y3.mul(&t0);
                 y3.add(&x3);
-                t1.copy(&self.x);
+                t1 = self.getpx();
                 t1.mul(&self.y);
-                self.x.copy(&t0);
+                self.x = t0.clone();
                 self.x.norm();
                 self.x.mul(&t1);
                 self.x.dbl();
                 self.x.norm();
-                self.y.copy(&y3);
+                self.y = y3.clone();
                 self.y.norm();
             } else {
-                let mut t0 = FP::new_copy(&self.x);
-                let mut t1 = FP::new_copy(&self.y);
-                let mut t2 = FP::new_copy(&self.z);
-                let mut t3 = FP::new_copy(&self.x);
-                let mut z3 = FP::new_copy(&self.z);
-                let mut y3 = FP::new();
-                let mut x3 = FP::new();
+                let mut t0 = self.x.clone();
+                let mut t1 = self.y.clone();
+                let mut t2 = self.z.clone();
+                let mut t3 = self.x.clone();
+                let mut z3 = self.z.clone();
                 let mut b = FP::new();
 
                 if rom::CURVE_B_I == 0 {
-                    b.copy(&FP::new_big(&Big::new_ints(&rom::CURVE_B)));
+                    b = FP::new_big(Big::new_ints(&rom::CURVE_B));
                 }
 
                 t0.sqr(); //1    x^2
@@ -527,7 +504,7 @@ impl ECP {
                 z3.mul(&self.x); //6
                 z3.dbl();
                 z3.norm(); //7
-                y3.copy(&t2);
+                let mut y3 = t2.clone();
 
                 if rom::CURVE_B_I == 0 {
                     y3.mul(&b); //8
@@ -536,19 +513,19 @@ impl ECP {
                 }
 
                 y3.sub(&z3); //9  ***
-                x3.copy(&y3);
+                let mut x3 = y3.clone();
                 x3.add(&y3);
                 x3.norm(); //10
 
                 y3.add(&x3); //11
-                x3.copy(&t1);
+                x3 = t1.clone();
                 x3.sub(&y3);
                 x3.norm(); //12
                 y3.add(&t1);
                 y3.norm(); //13
                 y3.mul(&x3); //14
                 x3.mul(&t3); //15
-                t3.copy(&t2);
+                t3 = t2.clone();
                 t3.add(&t2); //16
                 t2.add(&t3); //17
 
@@ -561,12 +538,12 @@ impl ECP {
                 z3.sub(&t2); //19
                 z3.sub(&t0);
                 z3.norm(); //20  ***
-                t3.copy(&z3);
+                t3 = z3.clone();
                 t3.add(&z3); //21
 
                 z3.add(&t3);
                 z3.norm(); //22
-                t3.copy(&t0);
+                t3 = t0.clone();
                 t3.add(&t0); //23
                 t0.add(&t3); //24
                 t0.sub(&t2);
@@ -574,7 +551,7 @@ impl ECP {
 
                 t0.mul(&z3); //26
                 y3.add(&t0); //27
-                t0.copy(&self.y);
+                t0 = self.getpy();
                 t0.mul(&self.z); //28
                 t0.dbl();
                 t0.norm(); //29
@@ -584,22 +561,21 @@ impl ECP {
                 t0.norm(); //32
                 t1.dbl();
                 t1.norm(); //33
-                z3.copy(&t0);
+                z3 = t0.clone();
                 z3.mul(&t1); //34
 
-                self.x.copy(&x3);
+                self.x = x3.clone();
                 self.x.norm();
-                self.y.copy(&y3);
+                self.y = y3.clone();
                 self.y.norm();
-                self.z.copy(&z3);
+                self.z = z3.clone();
                 self.z.norm();
             }
         }
         if CURVETYPE == CurveType::Edwards {
-            let mut c = FP::new_copy(&self.x);
-            let mut d = FP::new_copy(&self.y);
-            let mut h = FP::new_copy(&self.z);
-            let mut j = FP::new();
+            let mut c = self.x.clone();
+            let mut d = self.y.clone();
+            let mut h = self.z.clone();
 
             self.x.mul(&self.y);
             self.x.dbl();
@@ -609,13 +585,13 @@ impl ECP {
             if rom::CURVE_A == -1 {
                 c.neg()
             }
-            self.y.copy(&c);
+            self.y = c.clone();
             self.y.add(&d);
             self.y.norm();
             h.sqr();
             h.dbl();
-            self.z.copy(&self.y);
-            j.copy(&self.y);
+            self.z = self.getpy();
+            let mut j = self.getpy();
             j.sub(&h);
             j.norm();
             self.x.mul(&j);
@@ -625,36 +601,32 @@ impl ECP {
             self.z.mul(&j);
         }
         if CURVETYPE == CurveType::Montgomery {
-            let mut a = FP::new_copy(&self.x);
-            let mut b = FP::new_copy(&self.x);
-            let mut aa = FP::new();
-            let mut bb = FP::new();
-            let mut c = FP::new();
+            let mut a = self.x.clone();
+            let mut b = self.x.clone();
 
             a.add(&self.z);
             a.norm();
-            aa.copy(&a);
+            let mut aa = a.clone();
             aa.sqr();
             b.sub(&self.z);
             b.norm();
-            bb.copy(&b);
+            let mut bb = b.clone();
             bb.sqr();
-            c.copy(&aa);
+            let mut c = aa.clone();
             c.sub(&bb);
             c.norm();
 
-            self.x.copy(&aa);
+            self.x = aa.clone();
             self.x.mul(&bb);
 
-            a.copy(&c);
+            a = c.clone();
             a.imul((rom::CURVE_A + 2) / 4);
 
             bb.add(&a);
             bb.norm();
-            self.z.copy(&bb);
+            self.z = bb;
             self.z.mul(&c);
         }
-        return;
     }
 
     /* self+=Q */
@@ -662,64 +634,64 @@ impl ECP {
         if CURVETYPE == CurveType::Weierstrass {
             if rom::CURVE_A == 0 {
                 let b = 3 * rom::CURVE_B_I;
-                let mut t0 = FP::new_copy(&self.x);
+                let mut t0 = self.x.clone();
                 t0.mul(&Q.x);
-                let mut t1 = FP::new_copy(&self.y);
+                let mut t1 = self.y.clone();
                 t1.mul(&Q.y);
-                let mut t2 = FP::new_copy(&self.z);
+                let mut t2 = self.z.clone();
                 t2.mul(&Q.z);
-                let mut t3 = FP::new_copy(&self.x);
+                let mut t3 = self.x.clone();
                 t3.add(&self.y);
                 t3.norm();
-                let mut t4 = FP::new_copy(&Q.x);
+                let mut t4 = Q.x.clone();
                 t4.add(&Q.y);
                 t4.norm();
                 t3.mul(&t4);
-                t4.copy(&t0);
+                t4 = t0.clone();
                 t4.add(&t1);
 
                 t3.sub(&t4);
                 t3.norm();
-                t4.copy(&self.y);
+                t4 = self.getpy();
                 t4.add(&self.z);
                 t4.norm();
-                let mut x3 = FP::new_copy(&Q.y);
+                let mut x3 = Q.y.clone();
                 x3.add(&Q.z);
                 x3.norm();
 
                 t4.mul(&x3);
-                x3.copy(&t1);
+                x3 = t1.clone();
                 x3.add(&t2);
 
                 t4.sub(&x3);
                 t4.norm();
-                x3.copy(&self.x);
+                x3 = self.getpx();
                 x3.add(&self.z);
                 x3.norm();
-                let mut y3 = FP::new_copy(&Q.x);
+                let mut y3 = Q.x.clone();
                 y3.add(&Q.z);
                 y3.norm();
                 x3.mul(&y3);
-                y3.copy(&t0);
+                y3 = t0.clone();
                 y3.add(&t2);
                 y3.rsub(&x3);
                 y3.norm();
-                x3.copy(&t0);
+                x3 = t0.clone();
                 x3.add(&t0);
                 t0.add(&x3);
                 t0.norm();
                 t2.imul(b);
 
-                let mut z3 = FP::new_copy(&t1);
+                let mut z3 = t1.clone();
                 z3.add(&t2);
                 z3.norm();
                 t1.sub(&t2);
                 t1.norm();
                 y3.imul(b);
 
-                x3.copy(&y3);
+                x3 = y3.clone();
                 x3.mul(&t4);
-                t2.copy(&t3);
+                t2 = t3.clone();
                 t2.mul(&t1);
                 x3.rsub(&t2);
                 y3.mul(&t0);
@@ -729,25 +701,24 @@ impl ECP {
                 z3.mul(&t4);
                 z3.add(&t0);
 
-                self.x.copy(&x3);
+                self.x = x3.clone();
                 self.x.norm();
-                self.y.copy(&y3);
+                self.y = y3.clone();
                 self.y.norm();
-                self.z.copy(&z3);
+                self.z = z3.clone();
                 self.z.norm();
             } else {
-                let mut t0 = FP::new_copy(&self.x);
-                let mut t1 = FP::new_copy(&self.y);
-                let mut t2 = FP::new_copy(&self.z);
-                let mut t3 = FP::new_copy(&self.x);
-                let mut t4 = FP::new_copy(&Q.x);
-                let mut z3 = FP::new();
-                let mut y3 = FP::new_copy(&Q.x);
-                let mut x3 = FP::new_copy(&Q.y);
+                let mut t0 = self.x.clone();
+                let mut t1 = self.y.clone();
+                let mut t2 = self.z.clone();
+                let mut t3 = self.x.clone();
+                let mut t4 = Q.x.clone();
+                let mut y3 = Q.x.clone();
+                let mut x3 = Q.y.clone();
                 let mut b = FP::new();
 
                 if rom::CURVE_B_I == 0 {
-                    b.copy(&FP::new_big(&Big::new_ints(&rom::CURVE_B)));
+                    b = FP::new_big(Big::new_ints(&rom::CURVE_B));
                 }
 
                 t0.mul(&Q.x); //1
@@ -759,34 +730,34 @@ impl ECP {
                 t4.add(&Q.y);
                 t4.norm(); //5
                 t3.mul(&t4); //6
-                t4.copy(&t0);
+                t4 = t0.clone();
                 t4.add(&t1); //7
                 t3.sub(&t4);
                 t3.norm(); //8
-                t4.copy(&self.y);
+                t4 = self.getpy();
                 t4.add(&self.z);
                 t4.norm(); //9
                 x3.add(&Q.z);
                 x3.norm(); //10
                 t4.mul(&x3); //11
-                x3.copy(&t1);
+                x3 = t1.clone();
                 x3.add(&t2); //12
 
                 t4.sub(&x3);
                 t4.norm(); //13
-                x3.copy(&self.x);
+                x3 = self.getpx();
                 x3.add(&self.z);
                 x3.norm(); //14
                 y3.add(&Q.z);
                 y3.norm(); //15
 
                 x3.mul(&y3); //16
-                y3.copy(&t0);
+                y3 = t0.clone();
                 y3.add(&t2); //17
 
                 y3.rsub(&x3);
                 y3.norm(); //18
-                z3.copy(&t2);
+                let mut z3 = t2.clone();
 
                 if rom::CURVE_B_I == 0 {
                     z3.mul(&b); //18
@@ -794,14 +765,14 @@ impl ECP {
                     z3.imul(rom::CURVE_B_I);
                 }
 
-                x3.copy(&y3);
+                x3 = y3.clone();
                 x3.sub(&z3);
                 x3.norm(); //20
-                z3.copy(&x3);
+                z3 = x3.clone();
                 z3.add(&x3); //21
 
                 x3.add(&z3); //22
-                z3.copy(&t1);
+                z3 = t1.clone();
                 z3.sub(&x3);
                 z3.norm(); //23
                 x3.add(&t1);
@@ -813,7 +784,7 @@ impl ECP {
                     y3.imul(rom::CURVE_B_I);
                 }
 
-                t1.copy(&t2);
+                t1 = t2.clone();
                 t1.add(&t2); //t1.norm();//26
                 t2.add(&t1); //27
 
@@ -821,70 +792,66 @@ impl ECP {
 
                 y3.sub(&t0);
                 y3.norm(); //29
-                t1.copy(&y3);
+                t1 = y3.clone();
                 t1.add(&y3); //30
                 y3.add(&t1);
                 y3.norm(); //31
 
-                t1.copy(&t0);
+                t1 = t0.clone();
                 t1.add(&t0); //32
                 t0.add(&t1); //33
                 t0.sub(&t2);
                 t0.norm(); //34
-                t1.copy(&t4);
+                t1 = t4.clone();
                 t1.mul(&y3); //35
-                t2.copy(&t0);
+                t2 = t0.clone();
                 t2.mul(&y3); //36
-                y3.copy(&x3);
+                y3 = x3.clone();
                 y3.mul(&z3); //37
                 y3.add(&t2); //y3.norm();//38
                 x3.mul(&t3); //39
                 x3.sub(&t1); //40
                 z3.mul(&t4); //41
-                t1.copy(&t3);
+                t1 = t3.clone();
                 t1.mul(&t0); //42
                 z3.add(&t1);
-                self.x.copy(&x3);
+                self.x = x3.clone();
                 self.x.norm();
-                self.y.copy(&y3);
+                self.y = y3.clone();
                 self.y.norm();
-                self.z.copy(&z3);
+                self.z = z3.clone();
                 self.z.norm();
             }
         }
         if CURVETYPE == CurveType::Edwards {
-            let bb = FP::new_big(&Big::new_ints(&rom::CURVE_B));
-            let mut a = FP::new_copy(&self.z);
-            let mut b = FP::new();
-            let mut c = FP::new_copy(&self.x);
-            let mut d = FP::new_copy(&self.y);
-            let mut e = FP::new();
-            let mut f = FP::new();
-            let mut g = FP::new();
+            let bb = FP::new_big(Big::new_ints(&rom::CURVE_B));
+            let mut a = self.z.clone();
+            let mut c = self.x.clone();
+            let mut d = self.y.clone();
 
             a.mul(&Q.z);
-            b.copy(&a);
+            let mut b = a.clone();
             b.sqr();
             c.mul(&Q.x);
             d.mul(&Q.y);
 
-            e.copy(&c);
+            let mut e = c.clone();
             e.mul(&d);
             e.mul(&bb);
-            f.copy(&b);
+            let mut f = b.clone();
             f.sub(&e);
-            g.copy(&b);
+            let mut g = b.clone();
             g.add(&e);
 
             if rom::CURVE_A == 1 {
-                e.copy(&d);
+                e = d.clone();
                 e.sub(&c);
             }
             c.add(&d);
 
-            b.copy(&self.x);
+            b = self.getpx();
             b.add(&self.y);
-            d.copy(&Q.x);
+            d = Q.getpx();
             d.add(&Q.y);
             b.norm();
             d.norm();
@@ -893,21 +860,21 @@ impl ECP {
             b.norm();
             f.norm();
             b.mul(&f);
-            self.x.copy(&a);
+            self.x = a.clone();
             self.x.mul(&b);
             g.norm();
             if rom::CURVE_A == 1 {
                 e.norm();
-                c.copy(&e);
+                c = e.clone();
                 c.mul(&g);
             }
             if rom::CURVE_A == -1 {
                 c.norm();
                 c.mul(&g);
             }
-            self.y.copy(&a);
+            self.y = a.clone();
             self.y.mul(&c);
-            self.z.copy(&f);
+            self.z = f.clone();
             self.z.mul(&g);
         }
         return;
@@ -915,12 +882,10 @@ impl ECP {
 
     /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */
     pub fn dadd(&mut self, Q: &ECP, W: &ECP) {
-        let mut a = FP::new_copy(&self.x);
-        let mut b = FP::new_copy(&self.x);
-        let mut c = FP::new_copy(&Q.x);
-        let mut d = FP::new_copy(&Q.x);
-        let mut da = FP::new();
-        let mut cb = FP::new();
+        let mut a = self.x.clone();
+        let mut b = self.x.clone();
+        let mut c = Q.x.clone();
+        let mut d = Q.x.clone();
 
         a.add(&self.z);
         b.sub(&self.z);
@@ -931,64 +896,61 @@ impl ECP {
         a.norm();
         d.norm();
 
-        da.copy(&d);
+        let mut da  = d.clone();
         da.mul(&a);
 
         c.norm();
         b.norm();
 
-        cb.copy(&c);
+        let mut cb = c.clone();
         cb.mul(&b);
 
-        a.copy(&da);
+        a  = da.clone();
         a.add(&cb);
         a.norm();
         a.sqr();
-        b.copy(&da);
+        b = da.clone();
         b.sub(&cb);
         b.norm();
         b.sqr();
 
-        self.x.copy(&a);
-        self.z.copy(&W.x);
+        self.x = a.clone();
+        self.z = W.getpx();
         self.z.mul(&b);
     }
 
-    /* self-=Q */
+    /// self-=Q
     pub fn sub(&mut self, Q: &ECP) {
-        let mut NQ = ECP::new();
-        NQ.copy(Q);
+        let mut NQ = Q.clone();
         NQ.neg();
         self.add(&NQ);
     }
 
-    /* constant time multiply by small integer of length bts - use ladder */
+    // Constant time multiply by small integer of length bts - use ladder
     pub fn pinmul(&self, e: i32, bts: i32) -> ECP {
         if CURVETYPE == CurveType::Montgomery {
             return self.mul(&mut Big::new_int(e as isize));
         } else {
             let mut P = ECP::new();
             let mut R0 = ECP::new();
-            let mut R1 = ECP::new();
-            R1.copy(&self);
+            let mut R1 = self.clone();
 
             for i in (0..bts).rev() {
                 let b = ((e >> i) & 1) as isize;
-                P.copy(&R1);
+                P = R1.clone();
                 P.add(&R0);
                 R0.cswap(&mut R1, b);
-                R1.copy(&P);
+                R1 = P.clone();
                 R0.dbl();
                 R0.cswap(&mut R1, b);
             }
-            P.copy(&R0);
+            P = R0.clone();
             P.affine();
             return P;
         }
     }
 
-    /* return e.self */
-
+    /// Return e.self
     pub fn mul(&self, e: &Big) -> ECP {
         if e.iszilch() || self.is_infinity() {
             return ECP::new();
@@ -996,33 +958,24 @@ impl ECP {
         let mut P = ECP::new();
         if CURVETYPE == CurveType::Montgomery {
             /* use Ladder */
-            let mut D = ECP::new();
-            let mut R0 = ECP::new();
-            R0.copy(&self);
-            let mut R1 = ECP::new();
-            R1.copy(&self);
+            let mut R0 = self.clone();
+            let mut R1 = self.clone();
             R1.dbl();
-            D.copy(&self);
+            let mut D = self.clone();
             D.affine();
             let nb = e.nbits();
 
             for i in (0..nb - 1).rev() {
                 let b = e.bit(i);
-                P.copy(&R1);
+                P = R1.clone();
                 P.dadd(&mut R0, &D);
                 R0.cswap(&mut R1, b);
-                R1.copy(&P);
+                R1 = P.clone();
                 R0.dbl();
                 R0.cswap(&mut R1, b);
             }
-            P.copy(&R0)
+            P = R0.clone();
         } else {
-            // fixed size windows
-            let mut mt = Big::new();
-            let mut t = Big::new();
-            let mut Q = ECP::new();
-            let mut C = ECP::new();
-
             let mut W: [ECP; 8] = [
                 ECP::new(),
                 ECP::new(),
@@ -1037,29 +990,28 @@ impl ECP {
             const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4;
             let mut w: [i8; CT] = [0; CT];
 
-            Q.copy(&self);
+            let mut Q = self.clone();
             Q.dbl();
 
-            W[0].copy(&self);
+            W[0] = self.clone();
 
             for i in 1..8 {
-                C.copy(&W[i - 1]);
-                W[i].copy(&C);
+                W[i]  = W[i - 1].clone();
                 W[i].add(&Q);
             }
 
             // make exponent odd - add 2P if even, P if odd
-            t.copy(&e);
+            let mut t = e.clone();
             let s = t.parity();
             t.inc(1);
             t.norm();
             let ns = t.parity();
-            mt.copy(&t);
+            let mut mt = t.clone();
             mt.inc(1);
             mt.norm();
             t.cmove(&mt, s);
             Q.cmove(&self, ns);
-            C.copy(&Q);
+            let C = Q.clone();
 
             let nb = 1 + (t.nbits() + 3) / 4;
 
@@ -1072,7 +1024,7 @@ impl ECP {
             }
             w[nb] = t.lastbits(5) as i8;
 
-            P.copy(&W[((w[nb] as usize) - 1) / 2]);
+            P = W[((w[nb] as usize) - 1) / 2].clone();
             for i in (0..nb).rev() {
                 Q.selector(&W, w[i] as i32);
                 P.dbl();
@@ -1084,19 +1036,12 @@ impl ECP {
             P.sub(&C); /* apply correction */
         }
         P.affine();
-        return P;
+        P
     }
 
     /* Return e.this+f.Q */
 
     pub fn mul2(&self, e: &Big, Q: &ECP, f: &Big) -> ECP {
-        let mut te = Big::new();
-        let mut tf = Big::new();
-        let mut mt = Big::new();
-        let mut S = ECP::new();
-        let mut T = ECP::new();
-        let mut C = ECP::new();
-
         let mut W: [ECP; 8] = [
             ECP::new(),
             ECP::new(),
@@ -1111,36 +1056,36 @@ impl ECP {
         const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 1) / 2;
         let mut w: [i8; CT] = [0; CT];
 
-        te.copy(e);
-        tf.copy(f);
+        let mut te = e.clone();
+        let mut tf = f.clone();
 
         // precompute table
 
-        W[1].copy(&self);
+        W[1] = self.clone();
         W[1].sub(Q);
-        W[2].copy(&self);
+        W[2] = self.clone();
         W[2].add(Q);
-        S.copy(&Q);
+        let mut S = Q.clone();
         S.dbl();
-        C.copy(&W[1]);
-        W[0].copy(&C);
+        let mut C = W[1].clone();
+        W[0]  = C.clone();
         W[0].sub(&S); // copy to C is stupid Rust thing..
-        C.copy(&W[2]);
-        W[3].copy(&C);
+        C = W[2].clone();
+        W[3]  = C.clone();
         W[3].add(&S);
-        T.copy(&self);
+        let mut T = self.clone();
         T.dbl();
-        C.copy(&W[1]);
-        W[5].copy(&C);
+        C = W[1].clone();
+        W[5]  = C.clone();
         W[5].add(&T);
-        C.copy(&W[2]);
-        W[6].copy(&C);
+        C = W[2].clone();
+        W[6]  = C.clone();
         W[6].add(&T);
-        C.copy(&W[5]);
-        W[4].copy(&C);
+        C = W[5].clone();
+        W[4] = C.clone();
         W[4].sub(&S);
-        C.copy(&W[6]);
-        W[7].copy(&C);
+        C = W[6].clone();
+        W[7] = C.clone();
         W[7].add(&S);
 
         // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction
@@ -1149,25 +1094,25 @@ impl ECP {
         te.inc(1);
         te.norm();
         let mut ns = te.parity();
-        mt.copy(&te);
+        let mut mt = te.clone();
         mt.inc(1);
         mt.norm();
         te.cmove(&mt, s);
         T.cmove(&self, ns);
-        C.copy(&T);
+        C = T.clone();
 
         s = tf.parity();
         tf.inc(1);
         tf.norm();
         ns = tf.parity();
-        mt.copy(&tf);
+        mt = tf.clone();
         mt.inc(1);
         mt.norm();
         tf.cmove(&mt, s);
         S.cmove(&Q, ns);
         C.add(&S);
 
-        mt.copy(&te);
+        mt = te.clone();
         mt.add(&tf);
         mt.norm();
         let nb = 1 + (mt.nbits() + 1) / 2;
@@ -1185,7 +1130,7 @@ impl ECP {
             w[i] = (4 * a + b) as i8;
         }
         w[nb] = (4 * te.lastbits(3) + tf.lastbits(3)) as i8;
-        S.copy(&W[((w[nb] as usize) - 1) / 2]);
+        S = W[((w[nb] as usize) - 1) / 2].clone();
 
         for i in (0..nb).rev() {
             T.selector(&W, w[i] as i32);
@@ -1217,7 +1162,7 @@ impl ECP {
         }
         let c = Big::new_ints(&rom::CURVE_COF);
         let P = self.mul(&c);
-        self.copy(&P);
+        *self = P.clone();
     }
 
     // Map a given byte slice to a point on the curve. The byte slice should be atleast the size of the modulus
diff --git a/src/ecp2.rs b/src/ecp2.rs
index b0892e4..f86a005 100644
--- a/src/ecp2.rs
+++ b/src/ecp2.rs
@@ -26,7 +26,7 @@ use std::fmt;
 use std::str::SplitWhitespace;
 use types::{CurvePairingType, SexticTwist, SignOfX};
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct ECP2 {
     x: FP2,
     y: FP2,
@@ -62,32 +62,33 @@ impl ECP2 {
     }
     #[allow(non_snake_case)]
     /* construct this from (x,y) - but set to O if not on curve */
-    pub fn new_fp2s(ix: &FP2, iy: &FP2) -> ECP2 {
-        let mut E = ECP2::new();
-        E.x.copy(&ix);
-        E.y.copy(&iy);
-        E.z.one();
+    pub fn new_fp2s(x: FP2, y: FP2) -> ECP2 {
+        let mut E = ECP2 {
+            x,
+            y,
+            z: FP2::new_int(1),
+        };
         E.x.norm();
 
         let rhs = ECP2::rhs(&E.x);
-        let mut y2 = FP2::new_copy(&E.y);
+        let mut y2 = E.y.clone();
         y2.sqr();
         if !y2.equals(&rhs) {
             E.inf();
         }
-        return E;
+        E
     }
 
     /* construct this from x - but set to O if not on curve */
     pub fn new_fp2(ix: &FP2) -> ECP2 {
         let mut E = ECP2::new();
-        E.x.copy(&ix);
+        E.x = ix.clone();
         E.y.one();
         E.z.one();
         E.x.norm();
         let mut rhs = ECP2::rhs(&E.x);
         if rhs.sqrt() {
-            E.y.copy(&rhs);
+            E.y = rhs;
         } else {
             E.inf();
         }
@@ -99,13 +100,6 @@ impl ECP2 {
         self.x.iszilch() && self.z.iszilch()
     }
 
-    /* copy self=P */
-    pub fn copy(&mut self, P: &ECP2) {
-        self.x.copy(&P.x);
-        self.y.copy(&P.y);
-        self.z.copy(&P.z);
-    }
-
     /* set self=O */
     pub fn inf(&mut self) {
         self.x.zero();
@@ -136,7 +130,6 @@ impl ECP2 {
 
     /* Constant time select from pre-computed table */
     pub fn selector(&mut self, W: &[ECP2], b: i32) {
-        let mut MP = ECP2::new();
         let m = b >> 31;
         let mut babs = (b ^ m) - m;
 
@@ -151,24 +144,24 @@ impl ECP2 {
         self.cmove(&W[6], ECP2::teq(babs, 6));
         self.cmove(&W[7], ECP2::teq(babs, 7));
 
-        MP.copy(self);
+        let mut MP = self.clone();
         MP.neg();
         self.cmove(&MP, (m & 1) as isize);
     }
 
     /* Test if P == Q */
     pub fn equals(&self, Q: &ECP2) -> bool {
-        let mut a = FP2::new_copy(&self.x);
-        let mut b = FP2::new_copy(&Q.x);
+        let mut a = self.x.clone();
+        let mut b = Q.x.clone();
 
         a.mul(&Q.z);
         b.mul(&self.z);
         if !a.equals(&b) {
             return false;
         }
-        a.copy(&self.y);
+        a = self.getpy();
         a.mul(&Q.z);
-        b.copy(&Q.y);
+        b = Q.getpy();
         b.mul(&self.z);
         if !a.equals(&b) {
             return false;
@@ -192,44 +185,41 @@ impl ECP2 {
         self.x.reduce();
         self.y.mul(&self.z);
         self.y.reduce();
-        self.z.copy(&one);
+        self.z = one.clone();
     }
 
     /* extract affine x as FP2 */
     pub fn getx(&self) -> FP2 {
-        let mut W = ECP2::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
-        return FP2::new_copy(&W.x);
+        W.x.clone()
     }
 
     /* extract affine y as FP2 */
     pub fn gety(&self) -> FP2 {
-        let mut W = ECP2::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
-        return FP2::new_copy(&W.y);
+        W.y.clone()
     }
 
     /* extract projective x */
     pub fn getpx(&self) -> FP2 {
-        return FP2::new_copy(&self.x);
+        self.x.clone()
     }
     /* extract projective y */
     pub fn getpy(&self) -> FP2 {
-        return FP2::new_copy(&self.y);
+        self.y.clone()
     }
     /* extract projective z */
     pub fn getpz(&self) -> FP2 {
-        return FP2::new_copy(&self.z);
+        self.z.clone()
     }
 
     /* convert to byte array */
     pub fn tobytes(&self, b: &mut [u8]) {
         let mut t: [u8; big::MODBYTES as usize] = [0; big::MODBYTES as usize];
         let mb = big::MODBYTES as usize;
-        let mut W = ECP2::new();
-        W.copy(self);
+        let mut W = self.clone();
 
         W.affine();
         W.x.geta().tobytes(&mut t);
@@ -259,30 +249,29 @@ impl ECP2 {
         for i in 0..mb {
             t[i] = b[i]
         }
-        let mut ra = Big::frombytes(&t);
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + mb]
         }
-        let mut rb = Big::frombytes(&t);
-        let rx = FP2::new_bigs(&ra, &rb);
+        let rb = Big::frombytes(&t);
+        let rx = FP2::new_bigs(ra, rb);
 
         for i in 0..mb {
             t[i] = b[i + 2 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 3 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
-        let ry = FP2::new_bigs(&ra, &rb);
+        let rb = Big::frombytes(&t);
+        let ry = FP2::new_bigs(ra, rb);
 
-        return ECP2::new_fp2s(&rx, &ry);
+        ECP2::new_fp2s(rx, ry)
     }
 
     /* convert this to hex string */
     pub fn tostring(&self) -> String {
-        let mut W = ECP2::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
         if W.is_infinity() {
             return String::from("infinity");
@@ -314,9 +303,9 @@ impl ECP2 {
 
     /* Calculate RHS of twisted curve equation x^3+B/i */
     pub fn rhs(x: &FP2) -> FP2 {
-        let mut r = FP2::new_copy(x);
+        let mut r = x.clone();
         r.sqr();
-        let mut b = FP2::new_big(&Big::new_ints(&rom::CURVE_B));
+        let mut b = FP2::new_big(Big::new_ints(&rom::CURVE_B));
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             b.div_ip();
         }
@@ -335,23 +324,23 @@ impl ECP2 {
 
     /* self+=self */
     pub fn dbl(&mut self) -> isize {
-        let mut iy = FP2::new_copy(&self.y);
+        let mut iy = self.y.clone();
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             iy.mul_ip();
             iy.norm();
         }
 
-        let mut t0 = FP2::new_copy(&self.y); //***** Change
+        let mut t0 = self.y.clone(); //***** Change
         t0.sqr();
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             t0.mul_ip();
         }
-        let mut t1 = FP2::new_copy(&iy);
+        let mut t1 = iy.clone();
         t1.mul(&self.z);
-        let mut t2 = FP2::new_copy(&self.z);
+        let mut t2 = self.z.clone();
         t2.sqr();
 
-        self.z.copy(&t0);
+        self.z = t0.clone();
         self.z.add(&t0);
         self.z.norm();
         self.z.dbl();
@@ -363,15 +352,15 @@ impl ECP2 {
             t2.mul_ip();
             t2.norm();
         }
-        let mut x3 = FP2::new_copy(&t2);
+        let mut x3 = t2.clone();
         x3.mul(&self.z);
 
-        let mut y3 = FP2::new_copy(&t0);
+        let mut y3 = t0.clone();
 
         y3.add(&t2);
         y3.norm();
         self.z.mul(&t1);
-        t1.copy(&t2);
+        t1 = t2.clone();
         t1.add(&t2);
         t2.add(&t1);
         t2.norm();
@@ -379,15 +368,15 @@ impl ECP2 {
         t0.norm(); //y^2-9bz^2
         y3.mul(&t0);
         y3.add(&x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
-        t1.copy(&self.x);
+        t1 = self.x.clone();
         t1.mul(&iy); //
-        self.x.copy(&t0);
+        self.x = t0.clone();
         self.x.norm();
         self.x.mul(&t1);
         self.x.dbl(); //(y^2-9bz^2)xy2
 
         self.x.norm();
-        self.y.copy(&y3);
+        self.y = y3;
         self.y.norm();
 
         return 1;
@@ -396,21 +385,21 @@ impl ECP2 {
     /* self+=Q - return 0 for add, 1 for double, -1 for O */
     pub fn add(&mut self, Q: &ECP2) -> isize {
         let b = 3 * rom::CURVE_B_I;
-        let mut t0 = FP2::new_copy(&self.x);
+        let mut t0 = self.x.clone();
         t0.mul(&Q.x); // x.Q.x
-        let mut t1 = FP2::new_copy(&self.y);
+        let mut t1 = self.y.clone();
         t1.mul(&Q.y); // y.Q.y
 
-        let mut t2 = FP2::new_copy(&self.z);
+        let mut t2 = self.z.clone();
         t2.mul(&Q.z);
-        let mut t3 = FP2::new_copy(&self.x);
+        let mut t3 = self.x.clone();
         t3.add(&self.y);
         t3.norm(); //t3=X1+Y1
-        let mut t4 = FP2::new_copy(&Q.x);
+        let mut t4 = Q.x.clone();
         t4.add(&Q.y);
         t4.norm(); //t4=X2+Y2
         t3.mul(&t4); //t3=(X1+Y1)(X2+Y2)
-        t4.copy(&t0);
+        t4 = t0.clone();
         t4.add(&t1); //t4=X1.X2+Y1.Y2
 
         t3.sub(&t4);
@@ -419,15 +408,15 @@ impl ECP2 {
             t3.mul_ip();
             t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
         }
-        t4.copy(&self.y);
+        t4 = self.getpy();
         t4.add(&self.z);
         t4.norm(); //t4=Y1+Z1
-        let mut x3 = FP2::new_copy(&Q.y);
+        let mut x3 = Q.y.clone();
         x3.add(&Q.z);
         x3.norm(); //x3=Y2+Z2
 
         t4.mul(&x3); //t4=(Y1+Z1)(Y2+Z2)
-        x3.copy(&t1); //
+        x3 = t1.clone(); //
         x3.add(&t2); //X3=Y1.Y2+Z1.Z2
 
         t4.sub(&x3);
@@ -436,14 +425,14 @@ impl ECP2 {
             t4.mul_ip();
             t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
         }
-        x3.copy(&self.x);
+        x3 = self.getpx();
         x3.add(&self.z);
         x3.norm(); // x3=X1+Z1
-        let mut y3 = FP2::new_copy(&Q.x);
+        let mut y3 = Q.x.clone();
         y3.add(&Q.z);
         y3.norm(); // y3=X2+Z2
         x3.mul(&y3); // x3=(X1+Z1)(X2+Z2)
-        y3.copy(&t0);
+        y3 = t0.clone();
         y3.add(&t2); // y3=X1.X2+Z1+Z2
         y3.rsub(&x3);
         y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
@@ -454,7 +443,7 @@ impl ECP2 {
             t1.mul_ip();
             t1.norm(); // y.Q.y
         }
-        x3.copy(&t0);
+        x3 = t0.clone();
         x3.add(&t0);
         t0.add(&x3);
         t0.norm();
@@ -463,7 +452,7 @@ impl ECP2 {
             t2.mul_ip();
             t2.norm();
         }
-        let mut z3 = FP2::new_copy(&t1);
+        let mut z3 = t1.clone();
         z3.add(&t2);
         z3.norm();
         t1.sub(&t2);
@@ -473,9 +462,9 @@ impl ECP2 {
             y3.mul_ip();
             y3.norm();
         }
-        x3.copy(&y3);
+        x3 = y3.clone();
         x3.mul(&t4);
-        t2.copy(&t3);
+        t2 = t3.clone();
         t2.mul(&t1);
         x3.rsub(&t2);
         y3.mul(&t0);
@@ -485,11 +474,11 @@ impl ECP2 {
         z3.mul(&t4);
         z3.add(&t0);
 
-        self.x.copy(&x3);
+        self.x = x3;
         self.x.norm();
-        self.y.copy(&y3);
+        self.y = y3;
         self.y.norm();
-        self.z.copy(&z3);
+        self.z = z3;
         self.z.norm();
 
         return 0;
@@ -497,8 +486,7 @@ impl ECP2 {
 
     /* set this-=Q */
     pub fn sub(&mut self, Q: &ECP2) -> isize {
-        let mut NQ = ECP2::new();
-        NQ.copy(Q);
+        let mut NQ = Q.clone();
         NQ.neg();
         let d = self.add(&NQ);
         return d;
@@ -506,7 +494,7 @@ impl ECP2 {
 
     /* set this*=q, where q is Modulus, using Frobenius */
     pub fn frob(&mut self, x: &FP2) {
-        let mut x2 = FP2::new_copy(x);
+        let mut x2 = x.clone();
         x2.sqr();
         self.x.conj();
         self.y.conj();
@@ -519,15 +507,8 @@ impl ECP2 {
 
     /* self*=e */
     pub fn mul(&self, e: &Big) -> ECP2 {
-        /* fixed size windows */
-        let mut mt = Big::new();
-        let mut t = Big::new();
-        let mut P = ECP2::new();
-        let mut Q = ECP2::new();
-        let mut C = ECP2::new();
-
         if self.is_infinity() {
-            return P;
+            return ECP2::new();
         }
 
         let mut W: [ECP2; 8] = [
@@ -545,29 +526,28 @@ impl ECP2 {
         let mut w: [i8; CT] = [0; CT];
 
         /* precompute table */
-        Q.copy(&self);
+        let mut Q = self.clone();
         Q.dbl();
 
-        W[0].copy(&self);
+        W[0] = self.clone();
 
         for i in 1..8 {
-            C.copy(&W[i - 1]);
-            W[i].copy(&C);
+            W[i] = W[i - 1].clone();
             W[i].add(&Q);
         }
 
         /* make exponent odd - add 2P if even, P if odd */
-        t.copy(&e);
+        let mut t = e.clone();
         let s = t.parity();
         t.inc(1);
         t.norm();
         let ns = t.parity();
-        mt.copy(&t);
+        let mut mt = t.clone();
         mt.inc(1);
         mt.norm();
         t.cmove(&mt, s);
         Q.cmove(&self, ns);
-        C.copy(&Q);
+        let C = Q.clone();
 
         let nb = 1 + (t.nbits() + 3) / 4;
 
@@ -580,7 +560,7 @@ impl ECP2 {
         }
         w[nb] = (t.lastbits(5)) as i8;
 
-        P.copy(&W[((w[nb] as usize) - 1) / 2]);
+        let mut P = W[((w[nb] as usize) - 1) / 2].clone();
         for i in (0..nb).rev() {
             Q.selector(&W, w[i] as i32);
             P.dbl();
@@ -591,7 +571,7 @@ impl ECP2 {
         }
         P.sub(&C);
         P.affine();
-        return P;
+        P
     }
 
     /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 */
@@ -600,7 +580,6 @@ impl ECP2 {
     // Side channel attack secure
 
     pub fn mul4(Q: &mut [ECP2], u: &[Big]) -> ECP2 {
-        let mut W = ECP2::new();
         let mut P = ECP2::new();
 
         let mut T: [ECP2; 8] = [
@@ -616,12 +595,7 @@ impl ECP2 {
 
         let mut mt = Big::new();
 
-        let mut t: [Big; 4] = [
-            Big::new_copy(&u[0]),
-            Big::new_copy(&u[1]),
-            Big::new_copy(&u[2]),
-            Big::new_copy(&u[3]),
-        ];
+        let mut t: [Big; 4] = [u[0].clone(), u[1].clone(), u[2].clone(), u[3].clone()];
 
         const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize);
         let mut w: [i8; CT] = [0; CT];
@@ -631,26 +605,26 @@ impl ECP2 {
             t[i].norm();
         }
 
-        T[0].copy(&Q[0]);
-        W.copy(&T[0]);
-        T[1].copy(&W);
+        T[0] = Q[0].clone();
+        let mut W = T[0].clone();
+        T[1] = W.clone();
         T[1].add(&Q[1]); // Q[0]+Q[1]
-        T[2].copy(&W);
+        T[2] = W.clone();
         T[2].add(&Q[2]);
-        W.copy(&T[1]); // Q[0]+Q[2]
-        T[3].copy(&W);
+        W = T[1].clone(); // Q[0]+Q[2]
+        T[3] = W.clone();
         T[3].add(&Q[2]);
-        W.copy(&T[0]); // Q[0]+Q[1]+Q[2]
-        T[4].copy(&W);
+        W = T[0].clone(); // Q[0]+Q[1]+Q[2]
+        T[4] = W.clone();
         T[4].add(&Q[3]);
-        W.copy(&T[1]); // Q[0]+Q[3]
-        T[5].copy(&W);
+        W = T[1].clone(); // Q[0]+Q[3]
+        T[5] = W.clone();
         T[5].add(&Q[3]);
-        W.copy(&T[2]); // Q[0]+Q[1]+Q[3]
-        T[6].copy(&W);
+        W = T[2].clone(); // Q[0]+Q[1]+Q[3]
+        T[6] = W.clone();
         T[6].add(&Q[3]);
-        W.copy(&T[3]); // Q[0]+Q[2]+Q[3]
-        T[7].copy(&W);
+        W = T[3].clone(); // Q[0]+Q[2]+Q[3]
+        T[7] = W.clone();
         T[7].add(&Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
 
         // Make it odd
@@ -697,7 +671,7 @@ impl ECP2 {
         }
 
         // apply correction
-        W.copy(&P);
+        W = P.clone();
         W.sub(&Q[0]);
         P.cmove(&W, pb);
         P.affine();
@@ -714,7 +688,7 @@ impl ECP2 {
         let one = Big::new_int(1);
 
         loop {
-            let X = FP2::new_bigs(&one, &x);
+            let X = FP2::new_bigs(one.clone(), x.clone());
             Q = ECP2::new_fp2(&X);
             if !Q.is_infinity() {
                 break;
@@ -722,7 +696,7 @@ impl ECP2 {
             x.inc(1);
             x.norm();
         }
-        let mut X = FP2::new_bigs(&Big::new_ints(&rom::FRA), &Big::new_ints(&rom::FRB));
+        let mut X = FP2::new_bigs(Big::new_ints(&rom::FRA), Big::new_ints(&rom::FRB));
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             X.inverse();
             X.norm();
@@ -734,8 +708,7 @@ impl ECP2 {
             if ecp::SIGN_OF_X == SignOfX::NegativeX {
                 T.neg();
             }
-            let mut K = ECP2::new();
-            K.copy(&T);
+            let mut K = T.clone();
             K.dbl();
             K.add(&T);
 
@@ -771,18 +744,18 @@ impl ECP2 {
         }
 
         Q.affine();
-        return Q;
+        Q
     }
 
     pub fn generator() -> ECP2 {
         return ECP2::new_fp2s(
-            &FP2::new_bigs(
-                &Big::new_ints(&rom::CURVE_PXA),
-                &Big::new_ints(&rom::CURVE_PXB),
+            FP2::new_bigs(
+                Big::new_ints(&rom::CURVE_PXA),
+                Big::new_ints(&rom::CURVE_PXB),
             ),
-            &FP2::new_bigs(
-                &Big::new_ints(&rom::CURVE_PYA),
-                &Big::new_ints(&rom::CURVE_PYB),
+            FP2::new_bigs(
+                Big::new_ints(&rom::CURVE_PYA),
+                Big::new_ints(&rom::CURVE_PYB),
             ),
         );
     }
diff --git a/src/ecp4.rs b/src/ecp4.rs
index e0dc5dc..d7311b7 100644
--- a/src/ecp4.rs
+++ b/src/ecp4.rs
@@ -24,8 +24,8 @@ use super::fp2::FP2;
 use super::fp4::FP4;
 use super::rom;
 use types::{SexticTwist, SignOfX};
-//use std::str::SplitWhitespace;
 
+#[derive(Clone)]
 pub struct ECP4 {
     x: FP4,
     y: FP4,
@@ -45,13 +45,13 @@ impl ECP4 {
     /* construct this from (x,y) - but set to O if not on curve */
     pub fn new_fp4s(ix: &FP4, iy: &FP4) -> ECP4 {
         let mut E = ECP4::new();
-        E.x.copy(&ix);
-        E.y.copy(&iy);
+        E.x = ix.clone();
+        E.y = iy.clone();
         E.z.one();
         E.x.norm();
 
         let mut rhs = ECP4::rhs(&E.x);
-        let mut y2 = FP4::new_copy(&E.y);
+        let mut y2 = E.getpy();
         y2.sqr();
         if !y2.equals(&mut rhs) {
             E.inf();
@@ -62,14 +62,14 @@ impl ECP4 {
     /* construct this from x - but set to O if not on curve */
     pub fn new_fp4(ix: &FP4) -> ECP4 {
         let mut E = ECP4::new();
-        E.x.copy(&ix);
+        E.x = ix.clone();
         E.y.one();
         E.z.one();
         E.x.norm();
 
         let mut rhs = ECP4::rhs(&E.x);
         if rhs.sqrt() {
-            E.y.copy(&rhs);
+            E.y = rhs;
         } else {
             E.inf();
         }
@@ -78,18 +78,11 @@ impl ECP4 {
 
     /* Test this=O? */
     pub fn is_infinity(&self) -> bool {
-        let xx = FP4::new_copy(&self.x);
-        let zz = FP4::new_copy(&self.z);
+        let xx = self.getpx();
+        let zz = self.getpz();
         return xx.iszilch() && zz.iszilch();
     }
 
-    /* copy self=P */
-    pub fn copy(&mut self, P: &ECP4) {
-        self.x.copy(&P.x);
-        self.y.copy(&P.y);
-        self.z.copy(&P.z);
-    }
-
     /* set self=O */
     pub fn inf(&mut self) {
         self.x.zero();
@@ -120,7 +113,6 @@ impl ECP4 {
 
     /* Constant time select from pre-computed table */
     pub fn selector(&mut self, W: &[ECP4], b: i32) {
-        let mut MP = ECP4::new();
         let m = b >> 31;
         let mut babs = (b ^ m) - m;
 
@@ -135,24 +127,24 @@ impl ECP4 {
         self.cmove(&W[6], ECP4::teq(babs, 6));
         self.cmove(&W[7], ECP4::teq(babs, 7));
 
-        MP.copy(self);
+        let mut MP = self.clone();
         MP.neg();
         self.cmove(&MP, (m & 1) as isize);
     }
 
     /* Test if P == Q */
     pub fn equals(&mut self, Q: &mut ECP4) -> bool {
-        let mut a = FP4::new_copy(&self.x);
-        let mut b = FP4::new_copy(&Q.x);
+        let mut a = self.getpx();
+        let mut b = Q.getpx();
 
         a.mul(&Q.z);
         b.mul(&self.z);
         if !a.equals(&mut b) {
             return false;
         }
-        a.copy(&self.y);
+        a = self.getpy();
         a.mul(&Q.z);
-        b.copy(&Q.y);
+        b = Q.getpy();
         b.mul(&self.z);
         if !a.equals(&mut b) {
             return false;
@@ -176,36 +168,34 @@ impl ECP4 {
         self.x.reduce();
         self.y.mul(&self.z);
         self.y.reduce();
-        self.z.copy(&one);
+        self.z = one.clone();
     }
 
     /* extract affine x as FP4 */
     pub fn getx(&self) -> FP4 {
-        let mut W = ECP4::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
-        return FP4::new_copy(&self.x);
+        W.getpx()
     }
 
     /* extract affine y as FP4 */
     pub fn gety(&self) -> FP4 {
-        let mut W = ECP4::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
-        return FP4::new_copy(&W.y);
+        W.getpy()
     }
 
     /* extract projective x */
     pub fn getpx(&self) -> FP4 {
-        return FP4::new_copy(&self.x);
+        self.x.clone()
     }
     /* extract projective y */
     pub fn getpy(&self) -> FP4 {
-        return FP4::new_copy(&self.y);
+        self.y.clone()
     }
     /* extract projective z */
     pub fn getpz(&self) -> FP4 {
-        return FP4::new_copy(&self.z);
+        self.z.clone()
     }
 
     /* convert to byte array */
@@ -213,8 +203,7 @@ impl ECP4 {
         let mut t: [u8; big::MODBYTES as usize] = [0; big::MODBYTES as usize];
         let mb = big::MODBYTES as usize;
 
-        let mut W = ECP4::new();
-        W.copy(self);
+        let mut W = self.clone();
 
         W.affine();
 
@@ -263,58 +252,57 @@ impl ECP4 {
         for i in 0..mb {
             t[i] = b[i]
         }
-        let mut ra = Big::frombytes(&t);
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + mb]
         }
-        let mut rb = Big::frombytes(&t);
+        let rb = Big::frombytes(&t);
 
-        let mut ra4 = FP2::new_bigs(&ra, &rb);
+        let ra4 = FP2::new_bigs(ra, rb);
 
         for i in 0..mb {
             t[i] = b[i + 2 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 3 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        let mut rb4 = FP2::new_bigs(&ra, &rb);
+        let rb4 = FP2::new_bigs(ra, rb);
 
-        let rx = FP4::new_fp2s(&ra4, &rb4);
+        let rx = FP4::new_fp2s(ra4, rb4);
 
         for i in 0..mb {
             t[i] = b[i + 4 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 5 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        ra4.copy(&FP2::new_bigs(&ra, &rb));
+        let ra4 = FP2::new_bigs(ra, rb);
 
         for i in 0..mb {
             t[i] = b[i + 6 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 7 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        rb4.copy(&FP2::new_bigs(&ra, &rb));
+        let rb4 = FP2::new_bigs(ra, rb);
 
-        let ry = FP4::new_fp2s(&ra4, &rb4);
+        let ry = FP4::new_fp2s(ra4, rb4);
 
-        return ECP4::new_fp4s(&rx, &ry);
+        ECP4::new_fp4s(&rx, &ry)
     }
 
     /* convert this to hex string */
     pub fn tostring(&self) -> String {
-        let mut W = ECP4::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
         if W.is_infinity() {
             return String::from("infinity");
@@ -325,9 +313,9 @@ impl ECP4 {
     /* Calculate RHS of twisted curve equation x^3+B/i */
     pub fn rhs(x: &FP4) -> FP4 {
         //x.norm();
-        let mut r = FP4::new_copy(x);
+        let mut r = x.clone();
         r.sqr();
-        let mut b = FP4::new_fp2(&FP2::new_big(&Big::new_ints(&rom::CURVE_B)));
+        let mut b = FP4::new_fp2(FP2::new_big(Big::new_ints(&rom::CURVE_B)));
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             b.div_i();
         }
@@ -344,22 +332,22 @@ impl ECP4 {
 
     /* self+=self */
     pub fn dbl(&mut self) -> isize {
-        let mut iy = FP4::new_copy(&self.y);
+        let mut iy = self.getpy();
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             iy.times_i(); //iy.norm();
         }
 
-        let mut t0 = FP4::new_copy(&self.y);
+        let mut t0 = self.getpy();
         t0.sqr();
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             t0.times_i();
         }
-        let mut t1 = FP4::new_copy(&iy);
+        let mut t1 = iy.clone();
         t1.mul(&self.z);
-        let mut t2 = FP4::new_copy(&self.z);
+        let mut t2 = self.getpz();
         t2.sqr();
 
-        self.z.copy(&t0);
+        self.z = t0.clone();
         self.z.add(&t0);
         self.z.norm();
         self.z.dbl();
@@ -370,15 +358,15 @@ impl ECP4 {
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             t2.times_i();
         }
-        let mut x3 = FP4::new_copy(&t2);
+        let mut x3 = t2.clone();
         x3.mul(&self.z);
 
-        let mut y3 = FP4::new_copy(&t0);
+        let mut y3 = t0.clone();
 
         y3.add(&t2);
         y3.norm();
         self.z.mul(&t1);
-        t1.copy(&t2);
+        t1 = t2.clone();
         t1.add(&t2);
         t2.add(&t1);
         t2.norm();
@@ -386,15 +374,15 @@ impl ECP4 {
         t0.norm(); //y^2-9bz^2
         y3.mul(&t0);
         y3.add(&x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
-        t1.copy(&self.x);
+        t1 = self.getpx();
         t1.mul(&iy); //
-        self.x.copy(&t0);
+        self.x = t0.clone();
         self.x.norm();
         self.x.mul(&t1);
         self.x.dbl(); //(y^2-9bz^2)xy2
 
         self.x.norm();
-        self.y.copy(&y3);
+        self.y = y3.clone();
         self.y.norm();
 
         return 1;
@@ -403,21 +391,21 @@ impl ECP4 {
     /* self+=Q - return 0 for add, 1 for double, -1 for O */
     pub fn add(&mut self, Q: &ECP4) -> isize {
         let b = 3 * rom::CURVE_B_I;
-        let mut t0 = FP4::new_copy(&self.x);
+        let mut t0 = self.getpx();
         t0.mul(&Q.x); // x.Q.x
-        let mut t1 = FP4::new_copy(&self.y);
+        let mut t1 = self.getpy();
         t1.mul(&Q.y); // y.Q.y
 
-        let mut t2 = FP4::new_copy(&self.z);
+        let mut t2 = self.getpz();
         t2.mul(&Q.z);
-        let mut t3 = FP4::new_copy(&self.x);
+        let mut t3 = self.getpx();
         t3.add(&self.y);
         t3.norm(); //t3=X1+Y1
-        let mut t4 = FP4::new_copy(&Q.x);
+        let mut t4 = Q.getpx();
         t4.add(&Q.y);
         t4.norm(); //t4=X2+Y2
         t3.mul(&t4); //t3=(X1+Y1)(X2+Y2)
-        t4.copy(&t0);
+        t4 = t0.clone();
         t4.add(&t1); //t4=X1.X2+Y1.Y2
 
         t3.sub(&t4);
@@ -425,15 +413,15 @@ impl ECP4 {
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             t3.times_i(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
         }
-        t4.copy(&self.y);
+        t4 = self.getpy();
         t4.add(&self.z);
         t4.norm(); //t4=Y1+Z1
-        let mut x3 = FP4::new_copy(&Q.y);
+        let mut x3 = Q.getpy();
         x3.add(&Q.z);
         x3.norm(); //x3=Y2+Z2
 
         t4.mul(&x3); //t4=(Y1+Z1)(Y2+Z2)
-        x3.copy(&t1); //
+        x3 = t1.clone(); //
         x3.add(&t2); //X3=Y1.Y2+Z1.Z2
 
         t4.sub(&x3);
@@ -441,14 +429,14 @@ impl ECP4 {
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             t4.times_i(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
         }
-        x3.copy(&self.x);
+        x3 = self.getpx();
         x3.add(&self.z);
         x3.norm(); // x3=X1+Z1
-        let mut y3 = FP4::new_copy(&Q.x);
+        let mut y3 = Q.getpx();
         y3.add(&Q.z);
         y3.norm(); // y3=X2+Z2
         x3.mul(&y3); // x3=(X1+Z1)(X2+Z2)
-        y3.copy(&t0);
+        y3 = t0.clone();
         y3.add(&t2); // y3=X1.X2+Z1+Z2
         y3.rsub(&x3);
         y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
@@ -457,7 +445,7 @@ impl ECP4 {
             t0.times_i(); // x.Q.x
             t1.times_i(); // y.Q.y
         }
-        x3.copy(&t0);
+        x3 = t0.clone();
         x3.add(&t0);
         t0.add(&x3);
         t0.norm();
@@ -465,7 +453,7 @@ impl ECP4 {
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             t2.times_i();
         }
-        let mut z3 = FP4::new_copy(&t1);
+        let mut z3 = t1.clone();
         z3.add(&t2);
         z3.norm();
         t1.sub(&t2);
@@ -474,9 +462,9 @@ impl ECP4 {
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             y3.times_i();
         }
-        x3.copy(&y3);
+        x3 = y3.clone();
         x3.mul(&t4);
-        t2.copy(&t3);
+        t2 = t3.clone();
         t2.mul(&t1);
         x3.rsub(&t2);
         y3.mul(&t0);
@@ -486,11 +474,11 @@ impl ECP4 {
         z3.mul(&t4);
         z3.add(&t0);
 
-        self.x.copy(&x3);
+        self.x = x3.clone();
         self.x.norm();
-        self.y.copy(&y3);
+        self.y = y3.clone();
         self.y.norm();
-        self.z.copy(&z3);
+        self.z = z3.clone();
         self.z.norm();
 
         return 0;
@@ -498,29 +486,27 @@ impl ECP4 {
 
     /* set this-=Q */
     pub fn sub(&mut self, Q: &ECP4) -> isize {
-        let mut NQ = ECP4::new();
-        NQ.copy(Q);
+        let mut NQ = Q.clone();
         NQ.neg();
-        let d = self.add(&NQ);
-        return d;
+        self.add(&NQ)
     }
 
     pub fn frob_constants() -> [FP2; 3] {
-        let f = FP2::new_bigs(&Big::new_ints(&rom::FRA), &Big::new_ints(&rom::FRB));
+        let f = FP2::new_bigs(Big::new_ints(&rom::FRA), Big::new_ints(&rom::FRB));
 
-        let mut f0 = FP2::new_copy(&f);
+        let mut f0 = f.clone();
         f0.sqr();
-        let mut f2 = FP2::new_copy(&f0);
+        let mut f2 = f0.clone();
         f2.mul_ip();
         f2.norm();
-        let mut f1 = FP2::new_copy(&f2);
+        let mut f1 = f2.clone();
         f1.sqr();
         f2.mul(&f1);
-        f1.copy(&f);
+        f1 = f.clone();
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             f1.mul_ip();
             f1.inverse();
-            f0.copy(&f1);
+            f0 = f1.clone();
             f0.sqr();
         }
         f0.mul_ip();
@@ -548,14 +534,8 @@ impl ECP4 {
     /* self*=e */
     pub fn mul(&self, e: &Big) -> ECP4 {
         /* fixed size windows */
-        let mut mt = Big::new();
-        let mut t = Big::new();
-        let mut P = ECP4::new();
-        let mut Q = ECP4::new();
-        let mut C = ECP4::new();
-
         if self.is_infinity() {
-            return P;
+            return ECP4::new();
         }
 
         let mut W: [ECP4; 8] = [
@@ -573,29 +553,28 @@ impl ECP4 {
         let mut w: [i8; CT] = [0; CT];
 
         /* precompute table */
-        Q.copy(&self);
+        let mut Q = self.clone();
         Q.dbl();
 
-        W[0].copy(&self);
+        W[0] = self.clone();
 
         for i in 1..8 {
-            C.copy(&W[i - 1]);
-            W[i].copy(&C);
+            W[i] = W[i - 1].clone();
             W[i].add(&mut Q);
         }
 
         /* make exponent odd - add 2P if even, P if odd */
-        t.copy(&e);
+        let mut t = e.clone();
         let s = t.parity();
         t.inc(1);
         t.norm();
         let ns = t.parity();
-        mt.copy(&t);
+        let mut mt = t.clone();
         mt.inc(1);
         mt.norm();
         t.cmove(&mt, s);
         Q.cmove(&self, ns);
-        C.copy(&Q);
+        let mut C = Q.clone();
 
         let nb = 1 + (t.nbits() + 3) / 4;
 
@@ -608,7 +587,7 @@ impl ECP4 {
         }
         w[nb] = (t.lastbits(5)) as i8;
 
-        P.copy(&W[((w[nb] as usize) - 1) / 2]);
+        let mut P = W[((w[nb] as usize) - 1) / 2].clone();
         for i in (0..nb).rev() {
             Q.selector(&W, w[i] as i32);
             P.dbl();
@@ -619,7 +598,7 @@ impl ECP4 {
         }
         P.sub(&mut C);
         P.affine();
-        return P;
+        P
     }
 
     /* P=u0.Q0+u1*Q1+u2*Q2+u3*Q3.. */
@@ -628,7 +607,6 @@ impl ECP4 {
     // Side channel attack secure
 
     pub fn mul8(Q: &mut [ECP4], u: &[Big]) -> ECP4 {
-        let mut W = ECP4::new();
         let mut P = ECP4::new();
 
         let mut T1: [ECP4; 8] = [
@@ -655,14 +633,14 @@ impl ECP4 {
         let mut mt = Big::new();
 
         let mut t: [Big; 8] = [
-            Big::new_copy(&u[0]),
-            Big::new_copy(&u[1]),
-            Big::new_copy(&u[2]),
-            Big::new_copy(&u[3]),
-            Big::new_copy(&u[4]),
-            Big::new_copy(&u[5]),
-            Big::new_copy(&u[6]),
-            Big::new_copy(&u[7]),
+            u[0].clone(),
+            u[1].clone(),
+            u[2].clone(),
+            u[3].clone(),
+            u[4].clone(),
+            u[5].clone(),
+            u[6].clone(),
+            u[7].clone(),
         ];
 
         const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize);
@@ -676,32 +654,32 @@ impl ECP4 {
             t[i].norm();
         }
 
-        T1[0].copy(&Q[0]);
-        W.copy(&T1[0]);
-        T1[1].copy(&W);
+        T1[0] = Q[0].clone();
+        let mut W = T1[0].clone();
+        T1[1] = W.clone();
         T1[1].add(&mut Q[1]); // Q[0]+Q[1]
-        T1[2].copy(&W);
+        T1[2] = W.clone();
         T1[2].add(&mut Q[2]);
-        W.copy(&T1[1]); // Q[0]+Q[2]
-        T1[3].copy(&W);
+        W = T1[1].clone(); // Q[0]+Q[2]
+        T1[3] = W.clone();
         T1[3].add(&mut Q[2]);
-        W.copy(&T1[0]); // Q[0]+Q[1]+Q[2]
-        T1[4].copy(&W);
+        W = T1[0].clone(); // Q[0]+Q[1]+Q[2]
+        T1[4] = W.clone();
         T1[4].add(&mut Q[3]);
-        W.copy(&T1[1]); // Q[0]+Q[3]
-        T1[5].copy(&W);
+        W = T1[1].clone(); // Q[0]+Q[3]
+        T1[5] = W.clone();
         T1[5].add(&mut Q[3]);
-        W.copy(&T1[2]); // Q[0]+Q[1]+Q[3]
-        T1[6].copy(&W);
+        W = T1[2].clone(); // Q[0]+Q[1]+Q[3]
+        T1[6] = W.clone();
         T1[6].add(&mut Q[3]);
-        W.copy(&T1[3]); // Q[0]+Q[2]+Q[3]
-        T1[7].copy(&W);
+        W = T1[3].clone(); // Q[0]+Q[2]+Q[3]
+        T1[7] = W.clone();
         T1[7].add(&mut Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
 
         // Use frobenius
         let f = ECP4::frob_constants();
         for i in 0..8 {
-            T2[i].copy(&T1[i]);
+            T2[i] = T1[i].clone();
             T2[i].frob(&f, 4);
         }
 
@@ -771,11 +749,11 @@ impl ECP4 {
         }
 
         // apply correction
-        W.copy(&P);
+        W = P.clone();
         W.sub(&mut Q[0]);
         P.cmove(&W, pb1);
 
-        W.copy(&P);
+        W = P.clone();
         W.sub(&mut Q[4]);
         P.cmove(&W, pb2);
 
@@ -787,23 +765,23 @@ impl ECP4 {
     pub fn generator() -> ECP4 {
         return ECP4::new_fp4s(
             &FP4::new_fp2s(
-                &FP2::new_bigs(
-                    &Big::new_ints(&rom::CURVE_PXAA),
-                    &Big::new_ints(&rom::CURVE_PXAB),
+                FP2::new_bigs(
+                    Big::new_ints(&rom::CURVE_PXAA),
+                    Big::new_ints(&rom::CURVE_PXAB),
                 ),
-                &FP2::new_bigs(
-                    &Big::new_ints(&rom::CURVE_PXBA),
-                    &Big::new_ints(&rom::CURVE_PXBB),
+                FP2::new_bigs(
+                    Big::new_ints(&rom::CURVE_PXBA),
+                    Big::new_ints(&rom::CURVE_PXBB),
                 ),
             ),
             &FP4::new_fp2s(
-                &FP2::new_bigs(
-                    &Big::new_ints(&rom::CURVE_PYAA),
-                    &Big::new_ints(&rom::CURVE_PYAB),
+                FP2::new_bigs(
+                    Big::new_ints(&rom::CURVE_PYAA),
+                    Big::new_ints(&rom::CURVE_PYAB),
                 ),
-                &FP2::new_bigs(
-                    &Big::new_ints(&rom::CURVE_PYBA),
-                    &Big::new_ints(&rom::CURVE_PYBB),
+                FP2::new_bigs(
+                    Big::new_ints(&rom::CURVE_PYBA),
+                    Big::new_ints(&rom::CURVE_PYBB),
                 ),
             ),
         );
@@ -818,7 +796,7 @@ impl ECP4 {
         let one = Big::new_int(1);
 
         loop {
-            let X = FP4::new_fp2(&FP2::new_bigs(&one, &x));
+            let X = FP4::new_fp2(FP2::new_bigs(one.clone(), x.clone()));
             Q = ECP4::new_fp4(&X);
             if !Q.is_infinity() {
                 break;
diff --git a/src/ecp8.rs b/src/ecp8.rs
index 3998c2c..0261ce2 100644
--- a/src/ecp8.rs
+++ b/src/ecp8.rs
@@ -26,6 +26,7 @@ use super::fp8::FP8;
 use super::rom;
 use types::{SexticTwist, SignOfX};
 
+#[derive(Clone)]
 pub struct ECP8 {
     x: FP8,
     y: FP8,
@@ -45,13 +46,13 @@ impl ECP8 {
     /* construct this from (x,y) - but set to O if not on curve */
     pub fn new_fp8s(ix: &FP8, iy: &FP8) -> ECP8 {
         let mut E = ECP8::new();
-        E.x.copy(&ix);
-        E.y.copy(&iy);
+        E.x = ix.clone();
+        E.y = iy.clone();
         E.z.one();
         E.x.norm();
 
         let mut rhs = ECP8::rhs(&E.x);
-        let mut y2 = FP8::new_copy(&E.y);
+        let mut y2 = E.getpy();
         y2.sqr();
         if !y2.equals(&mut rhs) {
             E.inf();
@@ -62,14 +63,14 @@ impl ECP8 {
     /* construct this from x - but set to O if not on curve */
     pub fn new_fp8(ix: &FP8) -> ECP8 {
         let mut E = ECP8::new();
-        E.x.copy(&ix);
+        E.x = ix.clone();
         E.y.one();
         E.z.one();
         E.x.norm();
 
         let mut rhs = ECP8::rhs(&E.x);
         if rhs.sqrt() {
-            E.y.copy(&rhs);
+            E.y = rhs;
         } else {
             E.inf();
         }
@@ -78,18 +79,11 @@ impl ECP8 {
 
     /* Test this=O? */
     pub fn is_infinity(&self) -> bool {
-        let xx = FP8::new_copy(&self.x);
-        let zz = FP8::new_copy(&self.z);
+        let xx = self.getpx();
+        let zz = self.getpz();
         return xx.iszilch() && zz.iszilch();
     }
 
-    /* copy self=P */
-    pub fn copy(&mut self, P: &ECP8) {
-        self.x.copy(&P.x);
-        self.y.copy(&P.y);
-        self.z.copy(&P.z);
-    }
-
     /* set self=O */
     pub fn inf(&mut self) {
         self.x.zero();
@@ -120,7 +114,6 @@ impl ECP8 {
 
     /* Constant time select from pre-computed table */
     pub fn selector(&mut self, W: &[ECP8], b: i32) {
-        let mut MP = ECP8::new();
         let m = b >> 31;
         let mut babs = (b ^ m) - m;
 
@@ -135,24 +128,24 @@ impl ECP8 {
         self.cmove(&W[6], ECP8::teq(babs, 6));
         self.cmove(&W[7], ECP8::teq(babs, 7));
 
-        MP.copy(self);
+        let mut MP = self.clone();
         MP.neg();
         self.cmove(&MP, (m & 1) as isize);
     }
 
     /* Test if P == Q */
     pub fn equals(&mut self, Q: &mut ECP8) -> bool {
-        let mut a = FP8::new_copy(&self.x);
-        let mut b = FP8::new_copy(&Q.x);
+        let mut a = self.getpx();
+        let mut b = Q.getpx();
 
         a.mul(&Q.z);
         b.mul(&self.z);
         if !a.equals(&mut b) {
             return false;
         }
-        a.copy(&self.y);
+        a = self.getpy();
         a.mul(&Q.z);
-        b.copy(&Q.y);
+        b = Q.getpy();
         b.mul(&self.z);
         if !a.equals(&mut b) {
             return false;
@@ -176,44 +169,43 @@ impl ECP8 {
         self.x.reduce();
         self.y.mul(&self.z);
         self.y.reduce();
-        self.z.copy(&one);
+        self.z = one.clone();
     }
 
-    /* extract affine x as FP8 */
+    /// Extract affine x as FP8
     pub fn getx(&self) -> FP8 {
-        let mut W = ECP8::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
-        return FP8::new_copy(&W.x);
+        W.getpx()
     }
 
-    /* extract affine y as FP8 */
+    /// Extract affine y as FP8
     pub fn gety(&self) -> FP8 {
-        let mut W = ECP8::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
-        return FP8::new_copy(&W.y);
+        W.getpy()
     }
 
-    /* extract projective x */
+    /// Extract projective x
     pub fn getpx(&self) -> FP8 {
-        return FP8::new_copy(&self.x);
+        self.x.clone()
     }
-    /* extract projective y */
+
+    /// Extract projective y
     pub fn getpy(&self) -> FP8 {
-        return FP8::new_copy(&self.y);
+        self.y.clone()
     }
-    /* extract projective z */
+
+    // Extract projective z
     pub fn getpz(&self) -> FP8 {
-        return FP8::new_copy(&self.z);
+        self.z.clone()
     }
 
-    /* convert to byte array */
+    /// Convert to byte array
     pub fn tobytes(&self, b: &mut [u8]) {
         let mut t: [u8; big::MODBYTES as usize] = [0; big::MODBYTES as usize];
         let mb = big::MODBYTES as usize;
-        let mut W = ECP8::new();
-        W.copy(self);
+        let mut W = self.clone();
 
         W.affine();
 
@@ -298,110 +290,109 @@ impl ECP8 {
         for i in 0..mb {
             t[i] = b[i]
         }
-        let mut ra = Big::frombytes(&t);
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + mb]
         }
-        let mut rb = Big::frombytes(&t);
+        let rb = Big::frombytes(&t);
 
-        let mut ra4 = FP2::new_bigs(&ra, &rb);
+        let ra4 = FP2::new_bigs(ra, rb);
 
         for i in 0..mb {
             t[i] = b[i + 2 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 3 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        let mut rb4 = FP2::new_bigs(&ra, &rb);
+        let rb4 = FP2::new_bigs(ra, rb);
 
-        let mut ra8 = FP4::new_fp2s(&ra4, &rb4);
+        let ra8 = FP4::new_fp2s(ra4, rb4);
 
         for i in 0..mb {
             t[i] = b[i + 4 * mb]
         }
-        let mut ra = Big::frombytes(&t);
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 5 * mb]
         }
-        let mut rb = Big::frombytes(&t);
+        let rb = Big::frombytes(&t);
 
-        ra4.copy(&FP2::new_bigs(&ra, &rb));
+        let ra4 = FP2::new_bigs(ra, rb);
 
         for i in 0..mb {
             t[i] = b[i + 6 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 7 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        rb4.copy(&FP2::new_bigs(&ra, &rb));
+        let rb4 = FP2::new_bigs(ra, rb);
 
-        let mut rb8 = FP4::new_fp2s(&ra4, &rb4);
+        let rb8 = FP4::new_fp2s(ra4, rb4);
 
-        let rx = FP8::new_fp4s(&ra8, &rb8);
+        let rx = FP8::new_fp4s(ra8, rb8);
 
         for i in 0..mb {
             t[i] = b[i + 8 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 9 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        ra4.copy(&FP2::new_bigs(&ra, &rb));
+        let ra4 = FP2::new_bigs(ra, rb);
 
         for i in 0..mb {
             t[i] = b[i + 10 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 11 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        rb4.copy(&FP2::new_bigs(&ra, &rb));
+        let rb4 = FP2::new_bigs(ra, rb);
 
-        ra8.copy(&FP4::new_fp2s(&ra4, &rb4));
+        let ra8 = FP4::new_fp2s(ra4, rb4);
 
         for i in 0..mb {
             t[i] = b[i + 12 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 13 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        ra4.copy(&FP2::new_bigs(&ra, &rb));
+        let ra4 = FP2::new_bigs(ra, rb);
 
         for i in 0..mb {
             t[i] = b[i + 14 * mb]
         }
-        ra.copy(&Big::frombytes(&t));
+        let ra = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = b[i + 15 * mb]
         }
-        rb.copy(&Big::frombytes(&t));
+        let rb = Big::frombytes(&t);
 
-        rb4.copy(&FP2::new_bigs(&ra, &rb));
+        let rb4 = FP2::new_bigs(ra, rb);
 
-        rb8.copy(&FP4::new_fp2s(&ra4, &rb4));
+        let rb8 = FP4::new_fp2s(ra4, rb4);
 
-        let ry = FP8::new_fp4s(&ra8, &rb8);
+        let ry = FP8::new_fp4s(ra8, rb8);
 
         return ECP8::new_fp8s(&rx, &ry);
     }
 
     /* convert this to hex string */
     pub fn tostring(&self) -> String {
-        let mut W = ECP8::new();
-        W.copy(self);
+        let mut W = self.clone();
         W.affine();
         if W.is_infinity() {
             return String::from("infinity");
@@ -411,9 +402,9 @@ impl ECP8 {
 
     /* Calculate RHS of twisted curve equation x^3+B/i */
     pub fn rhs(x: &FP8) -> FP8 {
-        let mut r = FP8::new_copy(x);
+        let mut r = x.clone();
         r.sqr();
-        let mut b = FP8::new_fp4(&FP4::new_fp2(&FP2::new_big(&Big::new_ints(&rom::CURVE_B))));
+        let mut b = FP8::new_fp4(FP4::new_fp2(FP2::new_big(Big::new_ints(&rom::CURVE_B))));
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             b.div_i();
         }
@@ -430,22 +421,22 @@ impl ECP8 {
 
     /* self+=self */
     pub fn dbl(&mut self) -> isize {
-        let mut iy = FP8::new_copy(&self.y);
+        let mut iy = self.getpy();
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             iy.times_i(); //iy.norm();
         }
 
-        let mut t0 = FP8::new_copy(&self.y);
+        let mut t0 = self.getpy();
         t0.sqr();
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             t0.times_i();
         }
-        let mut t1 = FP8::new_copy(&iy);
+        let mut t1 = iy.clone();
         t1.mul(&self.z);
-        let mut t2 = FP8::new_copy(&self.z);
+        let mut t2 = self.getpz();
         t2.sqr();
 
-        self.z.copy(&t0);
+        self.z = t0.clone();
         self.z.add(&t0);
         self.z.norm();
         self.z.dbl();
@@ -456,15 +447,15 @@ impl ECP8 {
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             t2.times_i();
         }
-        let mut x3 = FP8::new_copy(&t2);
+        let mut x3 = t2.clone();
         x3.mul(&self.z);
 
-        let mut y3 = FP8::new_copy(&t0);
+        let mut y3 = t0.clone();
 
         y3.add(&t2);
         y3.norm();
         self.z.mul(&t1);
-        t1.copy(&t2);
+        t1 = t2.clone();
         t1.add(&t2);
         t2.add(&t1);
         t2.norm();
@@ -472,15 +463,15 @@ impl ECP8 {
         t0.norm(); //y^2-9bz^2
         y3.mul(&t0);
         y3.add(&x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
-        t1.copy(&self.x);
+        t1 = self.getpx();
         t1.mul(&iy); //
-        self.x.copy(&t0);
+        self.x = t0.clone();
         self.x.norm();
         self.x.mul(&t1);
         self.x.dbl(); //(y^2-9bz^2)xy2
 
         self.x.norm();
-        self.y.copy(&y3);
+        self.y = y3.clone();
         self.y.norm();
 
         return 1;
@@ -489,21 +480,21 @@ impl ECP8 {
     /* self+=Q - return 0 for add, 1 for double, -1 for O */
     pub fn add(&mut self, Q: &ECP8) -> isize {
         let b = 3 * rom::CURVE_B_I;
-        let mut t0 = FP8::new_copy(&self.x);
+        let mut t0 = self.getpx();
         t0.mul(&Q.x); // x.Q.x
-        let mut t1 = FP8::new_copy(&self.y);
+        let mut t1 = self.getpy();
         t1.mul(&Q.y); // y.Q.y
 
-        let mut t2 = FP8::new_copy(&self.z);
+        let mut t2 = self.getpz();
         t2.mul(&Q.z);
-        let mut t3 = FP8::new_copy(&self.x);
+        let mut t3 = self.getpx();
         t3.add(&self.y);
         t3.norm(); //t3=X1+Y1
-        let mut t4 = FP8::new_copy(&Q.x);
+        let mut t4 = Q.getpx();
         t4.add(&Q.y);
         t4.norm(); //t4=X2+Y2
         t3.mul(&t4); //t3=(X1+Y1)(X2+Y2)
-        t4.copy(&t0);
+        t4 = t0.clone();
         t4.add(&t1); //t4=X1.X2+Y1.Y2
 
         t3.sub(&t4);
@@ -511,15 +502,15 @@ impl ECP8 {
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             t3.times_i(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
         }
-        t4.copy(&self.y);
+        t4 = self.getpy();
         t4.add(&self.z);
         t4.norm(); //t4=Y1+Z1
-        let mut x3 = FP8::new_copy(&Q.y);
+        let mut x3 = Q.getpy();
         x3.add(&Q.z);
         x3.norm(); //x3=Y2+Z2
 
         t4.mul(&x3); //t4=(Y1+Z1)(Y2+Z2)
-        x3.copy(&t1); //
+        x3 = t1.clone(); //
         x3.add(&t2); //X3=Y1.Y2+Z1.Z2
 
         t4.sub(&x3);
@@ -527,14 +518,14 @@ impl ECP8 {
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
             t4.times_i(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
         }
-        x3.copy(&self.x);
+        x3 = self.getpx();
         x3.add(&self.z);
         x3.norm(); // x3=X1+Z1
-        let mut y3 = FP8::new_copy(&Q.x);
+        let mut y3 = Q.getpx();
         y3.add(&Q.z);
         y3.norm(); // y3=X2+Z2
         x3.mul(&y3); // x3=(X1+Z1)(X2+Z2)
-        y3.copy(&t0);
+        y3 = t0.clone();
         y3.add(&t2); // y3=X1.X2+Z1+Z2
         y3.rsub(&x3);
         y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
@@ -543,7 +534,7 @@ impl ECP8 {
             t0.times_i(); // x.Q.x
             t1.times_i(); // y.Q.y
         }
-        x3.copy(&t0);
+        x3 = t0.clone();
         x3.add(&t0);
         t0.add(&x3);
         t0.norm();
@@ -551,7 +542,7 @@ impl ECP8 {
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             t2.times_i();
         }
-        let mut z3 = FP8::new_copy(&t1);
+        let mut z3 = t1.clone();
         z3.add(&t2);
         z3.norm();
         t1.sub(&t2);
@@ -560,9 +551,9 @@ impl ECP8 {
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             y3.times_i();
         }
-        x3.copy(&y3);
+        x3 = y3.clone();
         x3.mul(&t4);
-        t2.copy(&t3);
+        t2 = t3.clone();
         t2.mul(&t1);
         x3.rsub(&t2);
         y3.mul(&t0);
@@ -572,11 +563,11 @@ impl ECP8 {
         z3.mul(&t4);
         z3.add(&t0);
 
-        self.x.copy(&x3);
+        self.x = x3.clone();
         self.x.norm();
-        self.y.copy(&y3);
+        self.y = y3.clone();
         self.y.norm();
-        self.z.copy(&z3);
+        self.z = z3.clone();
         self.z.norm();
 
         return 0;
@@ -584,33 +575,32 @@ impl ECP8 {
 
     /* set this-=Q */
     pub fn sub(&mut self, Q: &ECP8) -> isize {
-        let mut NQ = ECP8::new();
-        NQ.copy(Q);
+        let mut NQ = Q.clone();
         NQ.neg();
         let d = self.add(&NQ);
         return d;
     }
 
     pub fn frob_constants() -> [FP2; 3] {
-        let f = FP2::new_bigs(&Big::new_ints(&rom::FRA), &Big::new_ints(&rom::FRB));
+        let f = FP2::new_bigs(Big::new_ints(&rom::FRA), Big::new_ints(&rom::FRB));
 
-        let mut f0 = FP2::new_copy(&f);
+        let mut f0 = f.clone();
         f0.sqr();
-        let mut f2 = FP2::new_copy(&f0);
+        let mut f2 = f0.clone();
         f2.mul_ip();
         f2.norm();
-        let mut f1 = FP2::new_copy(&f2);
+        let mut f1 = f2.clone();
         f1.sqr();
         f2.mul(&f1);
 
         f2.mul_ip();
         f2.norm();
 
-        f1.copy(&f);
+        f1 = f.clone();
         if ecp::SEXTIC_TWIST == SexticTwist::MType {
             f1.mul_ip();
             f1.inverse();
-            f0.copy(&f1);
+            f0 = f1.clone();
             f0.sqr();
         }
         f0.mul_ip();
@@ -650,11 +640,7 @@ impl ECP8 {
     /* self*=e */
     pub fn mul(&self, e: &Big) -> ECP8 {
         /* fixed size windows */
-        let mut mt = Big::new();
-        let mut t = Big::new();
         let mut P = ECP8::new();
-        let mut Q = ECP8::new();
-        let mut C = ECP8::new();
 
         if self.is_infinity() {
             return P;
@@ -675,29 +661,28 @@ impl ECP8 {
         let mut w: [i8; CT] = [0; CT];
 
         /* precompute table */
-        Q.copy(&self);
+        let mut Q = self.clone();
         Q.dbl();
 
-        W[0].copy(&self);
+        W[0] = self.clone();
 
         for i in 1..8 {
-            C.copy(&W[i - 1]);
-            W[i].copy(&C);
+            W[i] = W[i - 1].clone();
             W[i].add(&mut Q);
         }
 
         /* make exponent odd - add 2P if even, P if odd */
-        t.copy(&e);
+        let mut t = e.clone();
         let s = t.parity();
         t.inc(1);
         t.norm();
         let ns = t.parity();
-        mt.copy(&t);
+        let mut mt = t.clone();
         mt.inc(1);
         mt.norm();
         t.cmove(&mt, s);
         Q.cmove(&self, ns);
-        C.copy(&Q);
+        let mut C = Q.clone();
 
         let nb = 1 + (t.nbits() + 3) / 4;
 
@@ -710,7 +695,7 @@ impl ECP8 {
         }
         w[nb] = (t.lastbits(5)) as i8;
 
-        P.copy(&W[((w[nb] as usize) - 1) / 2]);
+        P = W[((w[nb] as usize) - 1) / 2].clone();
         for i in (0..nb).rev() {
             Q.selector(&W, w[i] as i32);
             P.dbl();
@@ -730,7 +715,6 @@ impl ECP8 {
     // Side channel attack secure
 
     pub fn mul16(Q: &mut [ECP8], u: &[Big]) -> ECP8 {
-        let mut W = ECP8::new();
         let mut P = ECP8::new();
 
         let mut T1: [ECP8; 8] = [
@@ -777,22 +761,22 @@ impl ECP8 {
         let mut mt = Big::new();
 
         let mut t: [Big; 16] = [
-            Big::new_copy(&u[0]),
-            Big::new_copy(&u[1]),
-            Big::new_copy(&u[2]),
-            Big::new_copy(&u[3]),
-            Big::new_copy(&u[4]),
-            Big::new_copy(&u[5]),
-            Big::new_copy(&u[6]),
-            Big::new_copy(&u[7]),
-            Big::new_copy(&u[8]),
-            Big::new_copy(&u[9]),
-            Big::new_copy(&u[10]),
-            Big::new_copy(&u[11]),
-            Big::new_copy(&u[12]),
-            Big::new_copy(&u[13]),
-            Big::new_copy(&u[14]),
-            Big::new_copy(&u[15]),
+            u[0].clone(),
+            u[1].clone(),
+            u[2].clone(),
+            u[3].clone(),
+            u[4].clone(),
+            u[5].clone(),
+            u[6].clone(),
+            u[7].clone(),
+            u[8].clone(),
+            u[9].clone(),
+            u[10].clone(),
+            u[11].clone(),
+            u[12].clone(),
+            u[13].clone(),
+            u[14].clone(),
+            u[15].clone(),
         ];
 
         const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize);
@@ -810,92 +794,92 @@ impl ECP8 {
             t[i].norm();
         }
 
-        T1[0].copy(&Q[0]);
-        W.copy(&T1[0]);
-        T1[1].copy(&W);
+        T1[0] = Q[0].clone();
+        let mut W = T1[0].clone();
+        T1[1] = W.clone();
         T1[1].add(&mut Q[1]); // Q[0]+Q[1]
-        T1[2].copy(&W);
+        T1[2] = W.clone();
         T1[2].add(&mut Q[2]);
-        W.copy(&T1[1]); // Q[0]+Q[2]
-        T1[3].copy(&W);
+        W = T1[1].clone(); // Q[0]+Q[2]
+        T1[3] = W.clone();
         T1[3].add(&mut Q[2]);
-        W.copy(&T1[0]); // Q[0]+Q[1]+Q[2]
-        T1[4].copy(&W);
+        W = T1[0].clone(); // Q[0]+Q[1]+Q[2]
+        T1[4] = W.clone();
         T1[4].add(&mut Q[3]);
-        W.copy(&T1[1]); // Q[0]+Q[3]
-        T1[5].copy(&W);
+        W = T1[1].clone(); // Q[0]+Q[3]
+        T1[5] = W.clone();
         T1[5].add(&mut Q[3]);
-        W.copy(&T1[2]); // Q[0]+Q[1]+Q[3]
-        T1[6].copy(&W);
+        W = T1[2].clone(); // Q[0]+Q[1]+Q[3]
+        T1[6] = W.clone();
         T1[6].add(&mut Q[3]);
-        W.copy(&T1[3]); // Q[0]+Q[2]+Q[3]
-        T1[7].copy(&W);
+        W = T1[3].clone(); // Q[0]+Q[2]+Q[3]
+        T1[7] = W.clone();
         T1[7].add(&mut Q[3]); // Q[0]+Q[1]+Q[2]+Q[3]
 
-        T2[0].copy(&Q[4]);
-        W.copy(&T2[0]);
-        T2[1].copy(&W);
+        T2[0] = Q[4].clone();
+        W = T2[0].clone();
+        T2[1] = W.clone();
         T2[1].add(&mut Q[5]); // Q[0]+Q[1]
-        T2[2].copy(&W);
+        T2[2] = W.clone();
         T2[2].add(&mut Q[6]);
-        W.copy(&T2[1]); // Q[0]+Q[2]
-        T2[3].copy(&W);
+        W = T2[1].clone(); // Q[0]+Q[2]
+        T2[3] = W.clone();
         T2[3].add(&mut Q[6]);
-        W.copy(&T2[0]); // Q[0]+Q[1]+Q[2]
-        T2[4].copy(&W);
+        W = T2[0].clone(); // Q[0]+Q[1]+Q[2]
+        T2[4] = W.clone();
         T2[4].add(&mut Q[7]);
-        W.copy(&T2[1]); // Q[0]+Q[3]
-        T2[5].copy(&W);
+        W = T2[1].clone(); // Q[0]+Q[3]
+        T2[5] = W.clone();
         T2[5].add(&mut Q[7]);
-        W.copy(&T2[2]); // Q[0]+Q[1]+Q[3]
-        T2[6].copy(&W);
+        W = T2[2].clone(); // Q[0]+Q[1]+Q[3]
+        T2[6] = W.clone();
         T2[6].add(&mut Q[7]);
-        W.copy(&T2[3]); // Q[0]+Q[2]+Q[3]
-        T2[7].copy(&W);
+        W = T2[3].clone(); // Q[0]+Q[2]+Q[3]
+        T2[7] = W.clone();
         T2[7].add(&mut Q[7]); // Q[0]+Q[1]+Q[2]+Q[3]
 
-        T3[0].copy(&Q[8]);
-        W.copy(&T3[0]);
-        T3[1].copy(&W);
+        T3[0] = Q[8].clone();
+        W = T3[0].clone();
+        T3[1] = W.clone();
         T3[1].add(&mut Q[9]); // Q[0]+Q[1]
-        T3[2].copy(&W);
+        T3[2] = W.clone();
         T3[2].add(&mut Q[10]);
-        W.copy(&T3[1]); // Q[0]+Q[2]
-        T3[3].copy(&W);
+        W = T3[1].clone(); // Q[0]+Q[2]
+        T3[3] = W.clone();
         T3[3].add(&mut Q[10]);
-        W.copy(&T3[0]); // Q[0]+Q[1]+Q[2]
-        T3[4].copy(&W);
+        W = T3[0].clone(); // Q[0]+Q[1]+Q[2]
+        T3[4] = W.clone();
         T3[4].add(&mut Q[11]);
-        W.copy(&T3[1]); // Q[0]+Q[3]
-        T3[5].copy(&W);
+        W = T3[1].clone(); // Q[0]+Q[3]
+        T3[5] = W.clone();
         T3[5].add(&mut Q[11]);
-        W.copy(&T3[2]); // Q[0]+Q[1]+Q[3]
-        T3[6].copy(&W);
+        W = T3[2].clone(); // Q[0]+Q[1]+Q[3]
+        T3[6] = W.clone();
         T3[6].add(&mut Q[11]);
-        W.copy(&T3[3]); // Q[0]+Q[2]+Q[3]
-        T3[7].copy(&W);
+        W = T3[3].clone(); // Q[0]+Q[2]+Q[3]
+        T3[7] = W.clone();
         T3[7].add(&mut Q[11]); // Q[0]+Q[1]+Q[2]+Q[3]
 
-        T4[0].copy(&Q[12]);
-        W.copy(&T4[0]);
-        T4[1].copy(&W);
+        T4[0] = Q[12].clone();
+        W = T4[0].clone();
+        T4[1] = W.clone();
         T4[1].add(&mut Q[13]); // Q[0]+Q[1]
-        T4[2].copy(&W);
+        T4[2] = W.clone();
         T4[2].add(&mut Q[14]);
-        W.copy(&T4[1]); // Q[0]+Q[2]
-        T4[3].copy(&W);
+        W = T4[1].clone(); // Q[0]+Q[2]
+        T4[3] = W.clone();
         T4[3].add(&mut Q[14]);
-        W.copy(&T4[0]); // Q[0]+Q[1]+Q[2]
-        T4[4].copy(&W);
+        W = T4[0].clone(); // Q[0]+Q[1]+Q[2]
+        T4[4] = W.clone();
         T4[4].add(&mut Q[15]);
-        W.copy(&T4[1]); // Q[0]+Q[3]
-        T4[5].copy(&W);
+        W = T4[1].clone(); // Q[0]+Q[3]
+        T4[5] = W.clone();
         T4[5].add(&mut Q[15]);
-        W.copy(&T4[2]); // Q[0]+Q[1]+Q[3]
-        T4[6].copy(&W);
+        W = T4[2].clone(); // Q[0]+Q[1]+Q[3]
+        T4[6] = W.clone();
         T4[6].add(&mut Q[15]);
-        W.copy(&T4[3]); // Q[0]+Q[2]+Q[3]
-        T4[7].copy(&W);
+        W = T4[3].clone(); // Q[0]+Q[2]+Q[3]
+        T4[7] = W.clone();
         T4[7].add(&mut Q[15]); // Q[0]+Q[1]+Q[2]+Q[3]
 
         // Make it odd
@@ -1005,19 +989,19 @@ impl ECP8 {
         }
 
         // apply correction
-        W.copy(&P);
+        W = P.clone();
         W.sub(&mut Q[0]);
         P.cmove(&W, pb1);
 
-        W.copy(&P);
+        W = P.clone();
         W.sub(&mut Q[4]);
         P.cmove(&W, pb2);
 
-        W.copy(&P);
+        W = P.clone();
         W.sub(&mut Q[8]);
         P.cmove(&W, pb3);
 
-        W.copy(&P);
+        W = P.clone();
         W.sub(&mut Q[12]);
         P.cmove(&W, pb4);
 
@@ -1029,46 +1013,46 @@ impl ECP8 {
     pub fn generator() -> ECP8 {
         return ECP8::new_fp8s(
             &FP8::new_fp4s(
-                &FP4::new_fp2s(
-                    &FP2::new_bigs(
-                        &Big::new_ints(&rom::CURVE_PXAAA),
-                        &Big::new_ints(&rom::CURVE_PXAAB),
+                FP4::new_fp2s(
+                    FP2::new_bigs(
+                        Big::new_ints(&rom::CURVE_PXAAA),
+                        Big::new_ints(&rom::CURVE_PXAAB),
                     ),
-                    &FP2::new_bigs(
-                        &Big::new_ints(&rom::CURVE_PXABA),
-                        &Big::new_ints(&rom::CURVE_PXABB),
+                    FP2::new_bigs(
+                        Big::new_ints(&rom::CURVE_PXABA),
+                        Big::new_ints(&rom::CURVE_PXABB),
                     ),
                 ),
-                &FP4::new_fp2s(
-                    &FP2::new_bigs(
-                        &Big::new_ints(&rom::CURVE_PXBAA),
-                        &Big::new_ints(&rom::CURVE_PXBAB),
+                FP4::new_fp2s(
+                    FP2::new_bigs(
+                        Big::new_ints(&rom::CURVE_PXBAA),
+                        Big::new_ints(&rom::CURVE_PXBAB),
                     ),
-                    &FP2::new_bigs(
-                        &Big::new_ints(&rom::CURVE_PXBBA),
-                        &Big::new_ints(&rom::CURVE_PXBBB),
+                    FP2::new_bigs(
+                        Big::new_ints(&rom::CURVE_PXBBA),
+                        Big::new_ints(&rom::CURVE_PXBBB),
                     ),
                 ),
             ),
             &FP8::new_fp4s(
-                &FP4::new_fp2s(
-                    &FP2::new_bigs(
-                        &Big::new_ints(&rom::CURVE_PYAAA),
-                        &Big::new_ints(&rom::CURVE_PYAAB),
+                FP4::new_fp2s(
+                    FP2::new_bigs(
+                        Big::new_ints(&rom::CURVE_PYAAA),
+                        Big::new_ints(&rom::CURVE_PYAAB),
                     ),
-                    &FP2::new_bigs(
-                        &Big::new_ints(&rom::CURVE_PYABA),
-                        &Big::new_ints(&rom::CURVE_PYABB),
+                    FP2::new_bigs(
+                        Big::new_ints(&rom::CURVE_PYABA),
+                        Big::new_ints(&rom::CURVE_PYABB),
                     ),
                 ),
-                &FP4::new_fp2s(
-                    &FP2::new_bigs(
-                        &Big::new_ints(&rom::CURVE_PYBAA),
-                        &Big::new_ints(&rom::CURVE_PYBAB),
+                FP4::new_fp2s(
+                    FP2::new_bigs(
+                        Big::new_ints(&rom::CURVE_PYBAA),
+                        Big::new_ints(&rom::CURVE_PYBAB),
                     ),
-                    &FP2::new_bigs(
-                        &Big::new_ints(&rom::CURVE_PYBBA),
-                        &Big::new_ints(&rom::CURVE_PYBBB),
+                    FP2::new_bigs(
+                        Big::new_ints(&rom::CURVE_PYBBA),
+                        Big::new_ints(&rom::CURVE_PYBBB),
                     ),
                 ),
             ),
@@ -1084,7 +1068,7 @@ impl ECP8 {
         let one = Big::new_int(1);
 
         loop {
-            let X = FP8::new_fp4(&FP4::new_fp2(&FP2::new_bigs(&one, &x)));
+            let X = FP8::new_fp4(FP4::new_fp2(FP2::new_bigs(one.clone(), x.clone())));
             Q = ECP8::new_fp8(&X);
             if !Q.is_infinity() {
                 break;
diff --git a/src/ff.rs b/src/ff.rs
index 316c156..0f23b87 100644
--- a/src/ff.rs
+++ b/src/ff.rs
@@ -39,6 +39,7 @@ pub const P_OMASK: Chunk = (-1) << (P_MBITS % big::BASEBITS);
 pub const P_FEXCESS: Chunk = 1 << (big::BASEBITS * big::NLEN - P_MBITS - 1);
 pub const P_TBITS: usize = P_MBITS % big::BASEBITS;
 
+#[derive(Clone)]
 pub struct FF {
     v: Vec<Big>,
     length: usize,
@@ -98,14 +99,14 @@ impl FF {
     /* copy from FF b */
     pub fn copy(&mut self, b: &FF) {
         for i in 0..self.length {
-            self.v[i].copy(&b.v[i]);
+            self.v[i] = b.v[i].clone();
         }
     }
 
     /* x=y<<n */
     pub fn dsucopy(&mut self, b: &FF) {
         for i in 0..b.length {
-            self.v[b.length + i].copy(&b.v[i]);
+            self.v[b.length + i] = b.v[i].clone();
             self.v[i].zero();
         }
     }
@@ -113,7 +114,7 @@ impl FF {
     /* x=y */
     pub fn dscopy(&mut self, b: &FF) {
         for i in 0..b.length {
-            self.v[i].copy(&b.v[i]);
+            self.v[i] = b.v[i].clone();
             self.v[b.length + i].zero();
         }
     }
@@ -121,7 +122,7 @@ impl FF {
     /* x=y>>n */
     pub fn sducopy(&mut self, b: &FF) {
         for i in 0..self.length {
-            self.v[i].copy(&b.v[self.length + i]);
+            self.v[i] = b.v[self.length + i].clone();
         }
     }
 
@@ -146,8 +147,8 @@ impl FF {
     pub fn shrw(&mut self, n: usize) {
         let mut t = Big::new();
         for i in 0..n {
-            t.copy(&self.v[i + n]);
-            self.v[i].copy(&t);
+            t = self.v[i + n].clone();
+            self.v[i] = t.clone();
             self.v[i + n].zero();
         }
     }
@@ -156,8 +157,8 @@ impl FF {
     pub fn shlw(&mut self, n: usize) {
         let mut t = Big::new();
         for i in 0..n {
-            t.copy(&self.v[i]);
-            self.v[n + i].copy(&t);
+            t = self.v[i].clone();
+            self.v[n + i] = t.clone();
             self.v[i].zero();
         }
     }
@@ -191,7 +192,7 @@ impl FF {
     /* recursive add */
     pub fn radd(&mut self, vp: usize, x: &FF, xp: usize, y: &FF, yp: usize, n: usize) {
         for i in 0..n {
-            self.v[vp + i].copy(&x.v[xp + i]);
+            self.v[vp + i] = x.v[xp + i].clone();
             self.v[vp + i].add(&y.v[yp + i]);
         }
     }
@@ -206,7 +207,7 @@ impl FF {
     pub fn rsinc(&mut self, n: usize) {
         let mut t = Big::new();
         for i in 0..n {
-            t.copy(&self.v[i]);
+            t = self.v[i].clone();
             self.v[n + i].add(&t);
         }
     }
@@ -214,7 +215,7 @@ impl FF {
     /* recursive sub */
     pub fn rsub(&mut self, vp: usize, x: &FF, xp: usize, y: &FF, yp: usize, n: usize) {
         for i in 0..n {
-            self.v[vp + i].copy(&x.v[xp + i]);
+            self.v[vp + i] = x.v[xp + i].clone();
             self.v[vp + i].sub(&y.v[yp + i]);
         }
     }
@@ -357,8 +358,8 @@ impl FF {
         n: usize,
     ) {
         if n == 1 {
-            let xx = Big::new_copy(&x.v[xp]);
-            let yy = Big::new_copy(&y.v[yp]);
+            let xx = x.v[xp].clone();
+            let yy = y.v[yp].clone();
             let mut d = Big::mul(&xx, &yy);
             self.v[vp + 1] = d.split(8 * big::MODBYTES);
             self.v[vp].dcopy(&d);
@@ -384,9 +385,9 @@ impl FF {
 
     fn karsqr(&mut self, vp: usize, x: &FF, xp: usize, t: *mut FF, tp: usize, n: usize) {
         if n == 1 {
-            let xx = Big::new_copy(&x.v[xp]);
+            let xx = x.v[xp].clone();
             let mut d = Big::sqr(&xx);
-            self.v[vp + 1].copy(&d.split(8 * big::MODBYTES));
+            self.v[vp + 1] = d.split(8 * big::MODBYTES);
             self.v[vp].dcopy(&d);
             return;
         }
@@ -416,7 +417,7 @@ impl FF {
     ) {
         if n == 1 {
             /* only calculate bottom half of product */
-            self.v[vp].copy(&Big::smul(&x.v[xp], &y.v[yp]));
+            self.v[vp] = Big::smul(&x.v[xp], &y.v[yp]);
             return;
         }
         let nd2 = n / 2;
@@ -643,7 +644,7 @@ impl FF {
         if n == 1 {
             let mut d = DBig::new_scopy(&(self.v[0]));
             d.shl(big::NLEN * (big::BASEBITS as usize));
-            self.v[0].copy(&d.dmod(&(m.v[0])));
+            self.v[0] = d.dmod(&(m.v[0]));
         } else {
             let mut d = FF::new_int(2 * n);
             d.dsucopy(&self);
@@ -655,11 +656,11 @@ impl FF {
         let n = m.length;
         if n == 1 {
             let mut d = DBig::new_scopy(&(self.v[0]));
-            self.v[0].copy(&Big::monty(
+            self.v[0] = Big::monty(
                 &(m.v[0]),
                 ((1 as Chunk) << big::BASEBITS) - md.v[0].w[0],
                 &mut d,
-            ));
+            );
         } else {
             let mut d = FF::new_int(2 * n);
             self.rmod(m);
@@ -684,7 +685,7 @@ impl FF {
         let mut u = FF::new_int(n);
 
         u.zero();
-        u.v[0].copy(&self.v[0]);
+        u.v[0] = self.v[0].clone();
         u.v[0].invmod2m();
 
         let mut i = 1;
@@ -720,11 +721,11 @@ impl FF {
     pub fn random(&mut self, rng: &mut RAND) {
         let n = self.length;
         for i in 0..n {
-            self.v[i].copy(&Big::random(rng))
+            self.v[i] = Big::random(rng)
         }
         /* make sure top bit is 1 */
         while self.v[n - 1].nbits() < (big::MODBYTES as usize) * 8 {
-            self.v[n - 1].copy(&Big::random(rng));
+            self.v[n - 1] = Big::random(rng);
         }
     }
 
@@ -734,7 +735,7 @@ impl FF {
         let mut d = FF::new_int(2 * n);
 
         for i in 0..2 * n {
-            d.v[i].copy(&Big::random(rng));
+            d.v[i] = Big::random(rng);
         }
         self.copy(&d.dmod(p));
     }
@@ -747,11 +748,11 @@ impl FF {
         let n = p.length;
         if n == 1 {
             let mut d = Big::mul(&self.v[0], &y.v[0]);
-            self.v[0].copy(&Big::monty(
+            self.v[0] = Big::monty(
                 &(p.v[0]),
                 ((1 as Chunk) << big::BASEBITS) - nd.v[0].w[0],
                 &mut d,
-            ));
+            );
         } else {
             let mut d = FF::mul(&self, y);
             self.copy(&d.reduce(p, nd));
@@ -766,11 +767,11 @@ impl FF {
         let n = p.length;
         if n == 1 {
             let mut d = Big::sqr(&self.v[0]);
-            self.v[0].copy(&Big::monty(
+            self.v[0] = Big::monty(
                 &(p.v[0]),
                 ((1 as Chunk) << big::BASEBITS) - nd.v[0].w[0],
                 &mut d,
-            ));
+            );
         } else {
             let mut d = FF::sqr(&self);
             d.norm();
diff --git a/src/fp.rs b/src/fp.rs
index 95cddff..4437d21 100644
--- a/src/fp.rs
+++ b/src/fp.rs
@@ -26,7 +26,7 @@ use super::rom;
 use std::str::FromStr;
 use types::ModType;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct FP {
     pub x: Big,
     pub xes: i32,
@@ -54,7 +54,7 @@ pub use super::rom::{MOD8, MODBITS, MODTYPE, SH};
 use std::fmt;
 use std::str::SplitWhitespace;
 
-pub const FEXCESS: i32 = ((1 as i32) << SH) - 1;
+pub const FEXCESS: i32 = (1 << SH) - 1;
 pub const OMASK: Chunk = (-1) << (MODBITS % big::BASEBITS);
 pub const TBITS: usize = MODBITS % big::BASEBITS; // Number of active bits in top word
 pub const TMASK: Chunk = (1 << TBITS) - 1;
@@ -75,25 +75,17 @@ impl FP {
         return f;
     }
 
-    pub fn new_copy(y: &FP) -> FP {
-        let mut f = FP::new();
-        f.x.copy(&(y.x));
-        f.xes = y.xes;
-        return f;
-    }
-
-    pub fn new_big(y: &Big) -> FP {
-        let mut f = FP::new();
-        f.x.copy(y);
+    pub fn new_big(x: Big) -> FP {
+        let mut f = FP { x, xes: 1 };
         f.nres();
-        return f;
+        f
     }
 
     pub fn nres(&mut self) {
         if MODTYPE != ModType::PseudoMersenne && MODTYPE != ModType::GeneralisedMersenne {
             let r = Big::new_ints(&rom::R2MODP);
             let mut d = Big::mul(&(self.x), &r);
-            self.x.copy(&FP::modulo(&mut d));
+            self.x = FP::modulo(&mut d);
             self.xes = 2;
         } else {
             self.xes = 1;
@@ -124,7 +116,7 @@ impl FP {
             let mut d = DBig::new_scopy(&(self.x));
             return FP::modulo(&mut d);
         }
-        Big::new_copy(&(self.x))
+        self.x.clone()
     }
 
     // reduce a DBig to a Big using the appropriate form of the modulus
@@ -206,7 +198,7 @@ impl FP {
     // reduce this mod Modulus
     pub fn reduce(&mut self) {
         let mut m = Big::new_ints(&rom::MODULUS);
-        let mut r = Big::new_copy(&m);
+        let mut r = m.clone();
         let mut sb: usize;
         self.x.norm();
         if self.xes > 16 {
@@ -232,20 +224,14 @@ impl FP {
 
     // test this=0?
     pub fn iszilch(&self) -> bool {
-        let mut a = FP::new_copy(self);
+        let mut a = self.clone();
         a.reduce();
         a.x.iszilch()
     }
 
-    // copy from FP b
-    pub fn copy(&mut self, b: &FP) {
-        self.x.copy(&(b.x));
-        self.xes = b.xes;
-    }
-
     // copy from Big b
     pub fn bcopy(&mut self, b: &Big) {
-        self.x.copy(&b);
+        self.x = b.clone();
         self.nres();
     }
 
@@ -289,7 +275,7 @@ impl FP {
         }
 
         let mut d = Big::mul(&(self.x), &(b.x));
-        self.x.copy(&FP::modulo(&mut d));
+        self.x = FP::modulo(&mut d);
         self.xes = 2;
     }
 
@@ -348,7 +334,7 @@ impl FP {
 
         if MODTYPE == ModType::PseudoMersenne || MODTYPE == ModType::GeneralisedMersenne {
             let mut d = self.x.pxmul(cc);
-            self.x.copy(&FP::modulo(&mut d));
+            self.x = FP::modulo(&mut d);
             self.xes = 2
         } else {
             if self.xes * (cc as i32) <= FEXCESS {
@@ -373,7 +359,7 @@ impl FP {
         }
 
         let mut d = Big::sqr(&(self.x));
-        self.x.copy(&FP::modulo(&mut d));
+        self.x = FP::modulo(&mut d);
         self.xes = 2
     }
 
@@ -397,7 +383,7 @@ impl FP {
 
     // self-=b
     pub fn sub(&mut self, b: &FP) {
-        let mut n = FP::new_copy(b);
+        let mut n = b.clone();
         n.neg();
         self.add(&n);
     }
@@ -438,37 +424,36 @@ impl FP {
             FP::new(),
         ];
         // phase 1
-        let mut t = FP::new();
-        xp[0].copy(&self); // 1
-        xp[1].copy(&self);
+        xp[0] = self.clone(); // 1
+        xp[1] = self.clone();
         xp[1].sqr(); // 2
-        t.copy(&xp[1]);
-        xp[2].copy(&t);
+        let mut t = xp[1].clone();
+        xp[2] = t.clone();
         xp[2].mul(&self); // 3
-        t.copy(&xp[2]);
-        xp[3].copy(&t);
+        t = xp[2].clone();
+        xp[3] = t.clone();
         xp[3].sqr(); // 6
-        t.copy(&xp[3]);
-        xp[4].copy(&t);
+        t = xp[3].clone();
+        xp[4] = t.clone();
         xp[4].sqr(); // 12
-        t.copy(&xp[4]);
+        t = xp[4].clone();
         t.mul(&xp[2]);
-        xp[5].copy(&t); // 15
-        t.copy(&xp[5]);
-        xp[6].copy(&t);
+        xp[5] = t.clone(); // 15
+        t = xp[5].clone();
+        xp[6] = t.clone();
         xp[6].sqr(); // 30
-        t.copy(&xp[6]);
-        xp[7].copy(&t);
+        t = xp[6].clone();
+        xp[7] = t.clone();
         xp[7].sqr(); // 60
-        t.copy(&xp[7]);
-        xp[8].copy(&t);
+        t = xp[7].clone();
+        xp[8] = t.clone();
         xp[8].sqr(); // 120
-        t.copy(&xp[8]);
-        xp[9].copy(&t);
+        t = xp[8].clone();
+        xp[9] = t.clone();
         xp[9].sqr(); // 240
-        t.copy(&xp[9]);
+        t = xp[9].clone();
         t.mul(&xp[5]);
-        xp[10].copy(&t); // 255
+        xp[10] = t.clone(); // 255
 
         let mut n = MODBITS as isize;
         let c: isize;
@@ -499,7 +484,7 @@ impl FP {
             while ac[i] > k {
                 i -= 1;
             }
-            key.copy(&xp[i]);
+            key = xp[i].clone();
             k -= ac[i];
         }
         while k != 0 {
@@ -511,31 +496,30 @@ impl FP {
             k -= ac[i];
         }
         // phase 2
-        t.copy(&xp[2]);
-        xp[1].copy(&t);
-        t.copy(&xp[5]);
-        xp[2].copy(&t);
-        t.copy(&xp[10]);
-        xp[3].copy(&t);
+        t = xp[2].clone();
+        xp[1] = t.clone();
+        t = xp[5].clone();
+        xp[2] = t.clone();
+        t = xp[10].clone();
+        xp[3] = t.clone();
 
         let mut j = 3;
         let mut m = 8;
         let nw = n - bw;
-        let mut r = FP::new();
 
         while 2 * m < nw {
-            t.copy(&xp[j]);
+            t = xp[j].clone();
             j += 1;
             for _ in 0..m {
                 t.sqr();
             }
-            r.copy(&xp[j - 1]);
+            let mut r = xp[j - 1].clone();
             r.mul(&t);
-            xp[j].copy(&r);
+            xp[j] = r.clone();
             m *= 2;
         }
         let mut lo = nw - m;
-        r.copy(&xp[j]);
+        let mut r = xp[j].clone();
 
         while lo != 0 {
             m /= 2;
@@ -544,11 +528,11 @@ impl FP {
                 continue;
             }
             lo -= m;
-            t.copy(&r);
+            t = r.clone();
             for _ in 0..m {
                 t.sqr();
             }
-            r.copy(&t);
+            r = t.clone();
             r.mul(&xp[j]);
         }
         // phase 3
@@ -560,7 +544,7 @@ impl FP {
         }
         if MODTYPE == ModType::GeneralisedMersenne {
             // Goldilocks ONLY
-            key.copy(&r);
+            key = r.clone();
             r.sqr();
             r.mul(&self);
             for _ in 0..=n {
@@ -575,7 +559,7 @@ impl FP {
         if MODTYPE == ModType::PseudoMersenne || MODTYPE == ModType::GeneralisedMersenne {
             let mut y = self.fpow();
             if MOD8 == 5 {
-                let mut t = FP::new_copy(self);
+                let mut t = self.clone();
                 t.sqr();
                 self.mul(&t);
                 y.sqr();
@@ -590,14 +574,14 @@ impl FP {
             m2.dec(2);
             m2.norm();
             let inv = self.pow(&mut m2);
-            self.copy(&inv);
+            *self = inv.clone();
         }
     }
 
     // return TRUE if self==a
     pub fn equals(&self, a: &FP) -> bool {
-        let mut f = FP::new_copy(self);
-        let mut s = FP::new_copy(a);
+        let mut f = self.clone();
+        let mut s = a.clone();
         f.reduce();
         s.reduce();
         if Big::comp(&(f.x), &(s.x)) == 0 {
@@ -630,7 +614,7 @@ impl FP {
         let mut w: [i8; CT] = [0; CT];
 
         self.norm();
-        let mut t = Big::new_copy(e);
+        let mut t = e.clone();
         t.norm();
         let nb = 1 + (t.nbits() + 3) / 4;
 
@@ -642,15 +626,13 @@ impl FP {
             t.fshr(4);
         }
         tb[0].one();
-        tb[1].copy(&self);
+        tb[1] = self.clone();
 
-        let mut c = FP::new();
         for i in 2..16 {
-            c.copy(&tb[i - 1]);
-            tb[i].copy(&c);
+            tb[i] = tb[i - 1].clone();
             tb[i].mul(&self);
         }
-        let mut r = FP::new_copy(&tb[w[nb - 1] as usize]);
+        let mut r = tb[w[nb - 1] as usize].clone();
         for i in (0..nb - 1).rev() {
             r.sqr();
             r.sqr();
@@ -668,7 +650,7 @@ impl FP {
 
         if MOD8 == 5 {
             let v: FP;
-            let mut i = FP::new_copy(self);
+            let mut i = self.clone();
             i.x.shl(1);
             if MODTYPE == ModType::PseudoMersenne || MODTYPE == ModType::GeneralisedMersenne {
                 v = i.fpow();
@@ -682,7 +664,7 @@ impl FP {
             i.mul(&v);
             i.mul(&v);
             i.x.dec(1);
-            let mut r = FP::new_copy(self);
+            let mut r = self.clone();
             r.mul(&v);
             r.mul(&i);
             r.reduce();
diff --git a/src/fp12.rs b/src/fp12.rs
index e0dc648..bac4b65 100644
--- a/src/fp12.rs
+++ b/src/fp12.rs
@@ -32,7 +32,7 @@ pub const SPARSER: usize = 2;
 pub const SPARSE: usize = 3;
 pub const DENSE: usize = 4;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct FP12 {
     a: FP4,
     b: FP4,
@@ -61,47 +61,36 @@ impl FP12 {
     }
 
     pub fn gettype(&self) -> usize {
-        return self.stype;
+        self.stype
     }
 
     pub fn new_int(a: isize) -> FP12 {
-        let mut f = FP12::new();
-        f.a.copy(&FP4::new_int(a));
-        f.b.zero();
-        f.c.zero();
-        if a == 1 {
-            f.stype = ONE;
-        } else {
-            f.stype = SPARSER;
-        }
-        return f;
-    }
+        let stype = if a == 1 { ONE } else { SPARSER };
 
-    pub fn new_copy(x: &FP12) -> FP12 {
-        let mut f = FP12::new();
-        f.a.copy(&x.a);
-        f.b.copy(&x.b);
-        f.c.copy(&x.c);
-        f.stype = x.stype;
-        return f;
+        FP12 {
+            a: FP4::new_int(a),
+            b: FP4::new(),
+            c: FP4::new(),
+            stype,
+        }
     }
 
-    pub fn new_fp4s(d: &FP4, e: &FP4, f: &FP4) -> FP12 {
-        let mut g = FP12::new();
-        g.a.copy(d);
-        g.b.copy(e);
-        g.c.copy(f);
-        g.stype = DENSE;
-        return g;
+    pub fn new_fp4s(a: FP4, b: FP4, c: FP4) -> FP12 {
+        FP12 {
+            a,
+            b,
+            c,
+            stype: DENSE,
+        }
     }
 
-    pub fn new_fp4(d: &FP4) -> FP12 {
-        let mut g = FP12::new();
-        g.a.copy(d);
-        g.b.zero();
-        g.c.zero();
-        g.stype = SPARSER;
-        return g;
+    pub fn new_fp4(a: FP4) -> FP12 {
+        FP12 {
+            a,
+            b: FP4::new(),
+            c: FP4::new(),
+            stype: SPARSER,
+        }
     }
 
     /* reduce components mod Modulus */
@@ -157,7 +146,7 @@ impl FP12 {
         self.cmove(&g[6], FP12::teq(babs, 6));
         self.cmove(&g[7], FP12::teq(babs, 7));
 
-        let mut invf = FP12::new_copy(self);
+        let mut invf = self.clone();
         invf.conj();
         self.cmove(&invf, (m & 1) as isize);
     }
@@ -174,23 +163,15 @@ impl FP12 {
     }
 
     pub fn geta(&self) -> FP4 {
-        self.a
+        self.a.clone()
     }
 
     pub fn getb(&self) -> FP4 {
-        self.b
+        self.b.clone()
     }
 
     pub fn getc(&mut self) -> FP4 {
-        self.c
-    }
-
-    /* copy self=x */
-    pub fn copy(&mut self, x: &FP12) {
-        self.a.copy(&x.a);
-        self.b.copy(&x.b);
-        self.c.copy(&x.c);
-        self.stype = x.stype;
+        self.c.clone()
     }
 
     /* set self=1 */
@@ -218,13 +199,12 @@ impl FP12 {
 
     /* Granger-Scott Unitary Squaring */
     pub fn usqr(&mut self) {
-        let mut a = FP4::new_copy(&self.a);
-        let mut b = FP4::new_copy(&self.c);
-        let mut c = FP4::new_copy(&self.b);
-        let mut d = FP4::new();
+        let mut a = self.geta();
+        let mut b = self.getc();
+        let mut c = self.getb();
 
         self.a.sqr();
-        d.copy(&self.a);
+        let mut d = self.geta();
         d.add(&self.a);
         self.a.add(&d);
 
@@ -236,13 +216,13 @@ impl FP12 {
         b.sqr();
         b.times_i();
 
-        d.copy(&b);
+        d = b.clone();
         d.add(&b);
         b.add(&d);
         b.norm();
 
         c.sqr();
-        d.copy(&c);
+        d = c.clone();
         d.add(&c);
         c.add(&d);
         c.norm();
@@ -264,10 +244,10 @@ impl FP12 {
             return;
         }
 
-        let mut a = FP4::new_copy(&self.a);
-        let mut b = FP4::new_copy(&self.b);
-        let mut c = FP4::new_copy(&self.c);
-        let mut d = FP4::new_copy(&self.a);
+        let mut a = self.geta();
+        let mut b = self.getb();
+        let mut c = self.getc();
+        let mut d = self.geta();
 
         a.sqr();
         b.mul(&self.c);
@@ -282,7 +262,7 @@ impl FP12 {
         self.c.norm();
         self.c.sqr();
 
-        self.a.copy(&a);
+        self.a = a.clone();
         a.add(&b);
         a.norm();
         a.add(&c);
@@ -295,7 +275,7 @@ impl FP12 {
 
         self.a.add(&b);
 
-        self.b.copy(&c);
+        self.b = c.clone();
         self.b.add(&d);
         self.c.add(&a);
         if self.stype == SPARSER {
@@ -308,12 +288,10 @@ impl FP12 {
 
     /* FP12 full multiplication self=self*y */
     pub fn mul(&mut self, y: &FP12) {
-        let mut z0 = FP4::new_copy(&self.a);
-        let mut z1 = FP4::new();
-        let mut z2 = FP4::new_copy(&self.b);
-        let mut z3 = FP4::new();
-        let mut t0 = FP4::new_copy(&self.a);
-        let mut t1 = FP4::new_copy(&y.a);
+        let mut z0 = self.geta();
+        let mut z2 = self.getb();
+        let mut t0 = self.geta();
+        let mut t1 = y.a.clone();
 
         z0.mul(&y.a);
         z2.mul(&y.b);
@@ -324,46 +302,46 @@ impl FP12 {
         t0.norm();
         t1.norm();
 
-        z1.copy(&t0);
+        let mut z1 = t0.clone();
         z1.mul(&t1);
-        t0.copy(&self.b);
+        t0 = self.getb();
         t0.add(&self.c);
-        t1.copy(&y.b);
+        t1 = y.getb();
         t1.add(&y.c);
 
         t0.norm();
         t1.norm();
 
-        z3.copy(&t0);
+        let mut z3 = t0.clone();
         z3.mul(&t1);
 
-        t0.copy(&z0);
+        t0 = z0.clone();
         t0.neg();
-        t1.copy(&z2);
+        t1 = z2.clone();
         t1.neg();
 
         z1.add(&t0);
-        self.b.copy(&z1);
+        self.b = z1.clone();
         self.b.add(&t1);
 
         z3.add(&t1);
         z2.add(&t0);
 
-        t0.copy(&self.a);
+        t0 = self.geta();
         t0.add(&self.c);
         t0.norm();
-        t1.copy(&y.a);
+        t1 = y.geta();
         t1.add(&y.c);
         t1.norm();
         t0.mul(&t1);
         z2.add(&t0);
 
-        t0.copy(&self.c);
+        t0 = self.getc();
         t0.mul(&y.c);
-        t1.copy(&t0);
+        t1 = t0.clone();
         t1.neg();
 
-        self.c.copy(&z2);
+        self.c = z2;
         self.c.add(&t1);
         z3.add(&t1);
         t0.times_i();
@@ -371,7 +349,7 @@ impl FP12 {
         z3.norm();
 
         z3.times_i();
-        self.a.copy(&z0);
+        self.a = z0;
         self.a.add(&z3);
         self.stype = DENSE;
         self.norm();
@@ -382,80 +360,75 @@ impl FP12 {
     /* Usually w is denser than y */
     pub fn ssmul(&mut self, y: &FP12) {
         if self.stype == ONE {
-            self.copy(&y);
+            *self = y.clone();
             return;
         }
         if y.stype == ONE {
             return;
         }
         if y.stype >= SPARSE {
-            let mut z0 = FP4::new_copy(&self.a);
-            let mut z1 = FP4::new_int(0);
-            let mut z2 = FP4::new_int(0);
-            let mut z3 = FP4::new_int(0);
+            let mut z0 = self.geta();
+            let mut z2 = FP4::new();
             z0.mul(&y.a);
 
             if ecp::SEXTIC_TWIST == SexticTwist::MType {
                 if y.stype == SPARSE || self.stype == SPARSE {
-                    let mut ga = FP2::new_int(0);
-                    let mut gb = FP2::new_int(0);
-
-                    gb.copy(&self.b.getb());
+                    let mut gb = self.b.getb();
                     gb.mul(&y.b.getb());
-                    ga.zero();
+                    let mut ga = FP2::new();
                     if y.stype != SPARSE {
-                        ga.copy(&self.b.getb());
+                        ga = self.b.getb();
                         ga.mul(&y.b.geta());
                     }
                     if self.stype != SPARSE {
-                        ga.copy(&self.b.geta());
+                        ga = self.b.geta();
                         ga.mul(&y.b.getb());
                     }
                     z2.set_fp2s(&ga, &gb);
                     z2.times_i();
                 } else {
-                    z2.copy(&self.b);
+                    z2 = self.getb();
                     z2.mul(&y.b);
                 }
             } else {
-                z2.copy(&self.b);
+                z2 = self.getb();
                 z2.mul(&y.b);
             }
-            let mut t0 = FP4::new_copy(&self.a);
-            let mut t1 = FP4::new_copy(&y.a);
+            let mut t0 = self.geta();
+            let mut t1 = y.a.clone();
             t0.add(&self.b);
             t0.norm();
             t1.add(&y.b);
             t1.norm();
 
-            z1.copy(&t0);
+            let mut z1 = t0.clone();
             z1.mul(&t1);
-            t0.copy(&self.b);
+            t0 = self.getb();
             t0.add(&self.c);
             t0.norm();
-            t1.copy(&y.b);
+            t1 = y.getb();
             t1.add(&y.c);
             t1.norm();
 
-            z3.copy(&t0);
+            let mut z3 = t0.clone();
             z3.mul(&t1);
 
-            t0.copy(&z0);
+            t0 = z0.clone();
             t0.neg();
-            t1.copy(&z2);
+            t1 = z2.clone();
             t1.neg();
 
             z1.add(&t0);
-            self.b.copy(&z1);
+            self.b = z1.clone();
             self.b.add(&t1);
 
             z3.add(&t1);
             z2.add(&t0);
 
-            t0.copy(&self.a);
+            t0 = self.geta();
             t0.add(&self.c);
             t0.norm();
-            t1.copy(&y.a);
+            t1 = y.geta();
             t1.add(&y.c);
             t1.norm();
 
@@ -464,40 +437,37 @@ impl FP12 {
 
             if ecp::SEXTIC_TWIST == SexticTwist::DType {
                 if y.stype == SPARSE || self.stype == SPARSE {
-                    let mut ga = FP2::new_int(0);
-                    let mut gb = FP2::new_int(0);
-
-                    ga.copy(&self.c.geta());
+                    let mut ga = self.c.geta();
                     ga.mul(&y.c.geta());
-                    gb.zero();
+                    let mut gb = FP2::new();
                     if y.stype != SPARSE {
-                        gb.copy(&self.c.geta());
+                        gb = self.c.geta();
                         gb.mul(&y.c.getb());
                     }
                     if self.stype != SPARSE {
-                        gb.copy(&self.c.getb());
+                        gb = self.c.getb();
                         gb.mul(&y.c.geta());
                     }
                     t0.set_fp2s(&ga, &gb);
                 } else {
-                    t0.copy(&self.c);
+                    t0 = self.getc();
                     t0.mul(&y.c);
                 }
             } else {
-                t0.copy(&self.c);
+                t0 = self.getc();
                 t0.mul(&y.c);
             }
-            t1.copy(&t0);
+            t1 = t0.clone();
             t1.neg();
 
-            self.c.copy(&z2);
+            self.c = z2.clone();
             self.c.add(&t1);
             z3.add(&t1);
             t0.times_i();
             self.b.add(&t0);
             z3.norm();
             z3.times_i();
-            self.a.copy(&z0);
+            self.a = z0.clone();
             self.a.add(&z3);
         } else {
             if self.stype == SPARSER {
@@ -506,11 +476,10 @@ impl FP12 {
             }
             if ecp::SEXTIC_TWIST == SexticTwist::DType {
                 // dense by sparser - 13m
-                let mut z0 = FP4::new_copy(&self.a);
-                let mut z2 = FP4::new_copy(&self.b);
-                let mut z3 = FP4::new_copy(&self.b);
-                let mut t0 = FP4::new_int(0);
-                let mut t1 = FP4::new_copy(&y.a);
+                let mut z0 = self.geta();
+                let mut z2 = self.getb();
+                let mut z3 = self.getb();
+                let mut t1 = y.a.clone();
 
                 z0.mul(&y.a);
                 z2.pmul(&y.b.geta());
@@ -524,9 +493,9 @@ impl FP12 {
                 z3.norm();
                 z3.pmul(&y.b.geta());
 
-                t0.copy(&z0);
+                let mut t0 = z0.clone();
                 t0.neg();
-                t1.copy(&z2);
+                t1 = z2.clone();
                 t1.neg();
 
                 self.b.add(&t0);
@@ -535,70 +504,66 @@ impl FP12 {
                 z3.add(&t1);
                 z2.add(&t0);
 
-                t0.copy(&self.a);
+                t0 = self.geta();
                 t0.add(&self.c);
                 t0.norm();
                 z3.norm();
                 t0.mul(&y.a);
-                self.c.copy(&z2);
+                self.c = z2.clone();
                 self.c.add(&t0);
 
                 z3.times_i();
-                self.a.copy(&z0);
+                self.a = z0.clone();
                 self.a.add(&z3);
             }
             if ecp::SEXTIC_TWIST == SexticTwist::MType {
-                let mut z0 = FP4::new_copy(&self.a);
-                let mut z1 = FP4::new();
-                let mut z2 = FP4::new();
-                let mut z3 = FP4::new();
-                let mut t0 = FP4::new_copy(&self.a);
-                let mut t1 = FP4::new();
+                let mut z0 = self.geta();
+                let mut t0 = self.geta();
 
                 z0.mul(&y.a);
                 t0.add(&self.b);
                 t0.norm();
 
-                z1.copy(&t0);
+                let mut z1 = t0.clone();
                 z1.mul(&y.a);
-                t0.copy(&self.b);
+                t0 = self.getb();
                 t0.add(&self.c);
                 t0.norm();
 
-                z3.copy(&t0);
+                let mut z3 = t0.clone();
                 z3.pmul(&y.c.getb());
                 z3.times_i();
 
-                t0.copy(&z0);
+                t0 = z0.clone();
                 t0.neg();
                 z1.add(&t0);
-                self.b.copy(&z1);
-                z2.copy(&t0);
+                self.b = z1.clone();
+                let mut z2 = t0.clone();
 
-                t0.copy(&self.a);
+                t0 = self.geta();
                 t0.add(&self.c);
                 t0.norm();
-                t1.copy(&y.a);
+                let mut t1 = y.geta();
                 t1.add(&y.c);
                 t1.norm();
 
                 t0.mul(&t1);
                 z2.add(&t0);
-                t0.copy(&self.c);
+                t0 = self.getc();
 
                 t0.pmul(&y.c.getb());
                 t0.times_i();
-                t1.copy(&t0);
+                t1 = t0.clone();
                 t1.neg();
 
-                self.c.copy(&z2);
+                self.c = z2;
                 self.c.add(&t1);
                 z3.add(&t1);
                 t0.times_i();
                 self.b.add(&t0);
                 z3.norm();
                 z3.times_i();
-                self.a.copy(&z0);
+                self.a = z0;
                 self.a.add(&z3);
             }
         }
@@ -609,49 +574,49 @@ impl FP12 {
     /* Special case of multiplication arises from special form of ATE pairing line function */
     pub fn smul(&mut self, y: &FP12) {
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
-            let mut w1 = FP2::new_copy(&self.a.geta());
-            let mut w2 = FP2::new_copy(&self.a.getb());
-            let mut w3 = FP2::new_copy(&self.b.geta());
+            let mut w1 = self.a.geta();
+            let mut w2 = self.a.getb();
+            let mut w3 = self.b.geta();
 
             w1.mul(&y.a.geta());
             w2.mul(&y.a.getb());
             w3.mul(&y.b.geta());
 
-            let mut ta = FP2::new_copy(&self.a.geta());
-            let mut tb = FP2::new_copy(&y.a.geta());
+            let mut ta = self.a.geta();
+            let mut tb = y.a.geta();
             ta.add(&self.a.getb());
             ta.norm();
             tb.add(&y.a.getb());
             tb.norm();
-            let mut tc = FP2::new_copy(&ta);
+            let mut tc = ta.clone();
             tc.mul(&tb);
-            let mut t = FP2::new_copy(&w1);
+            let mut t = w1.clone();
             t.add(&w2);
             t.neg();
             tc.add(&t);
 
-            ta.copy(&self.a.geta());
+            ta = self.a.geta();
             ta.add(&self.b.geta());
             ta.norm();
-            tb.copy(&y.a.geta());
+            tb = y.a.geta();
             tb.add(&y.b.geta());
             tb.norm();
-            let mut td = FP2::new_copy(&ta);
+            let mut td = ta.clone();
             td.mul(&tb);
-            t.copy(&w1);
+            t = w1.clone();
             t.add(&w3);
             t.neg();
             td.add(&t);
 
-            ta.copy(&self.a.getb());
+            ta = self.a.getb();
             ta.add(&self.b.geta());
             ta.norm();
-            tb.copy(&y.a.getb());
+            tb = y.a.getb();
             tb.add(&y.b.geta());
             tb.norm();
-            let mut te = FP2::new_copy(&ta);
+            let mut te = ta.clone();
             te.mul(&tb);
-            t.copy(&w2);
+            t = w2.clone();
             t.add(&w3);
             t.neg();
             te.add(&t);
@@ -666,49 +631,49 @@ impl FP12 {
             self.a.norm();
             self.b.norm();
         } else {
-            let mut w1 = FP2::new_copy(&self.a.geta());
-            let mut w2 = FP2::new_copy(&self.a.getb());
-            let mut w3 = FP2::new_copy(&self.c.getb());
+            let mut w1 = self.a.geta();
+            let mut w2 = self.a.getb();
+            let mut w3 = self.c.getb();
 
             w1.mul(&y.a.geta());
             w2.mul(&y.a.getb());
             w3.mul(&y.c.getb());
 
-            let mut ta = FP2::new_copy(&self.a.geta());
-            let mut tb = FP2::new_copy(&y.a.geta());
+            let mut ta = self.a.geta();
+            let mut tb = y.a.geta();
             ta.add(&self.a.getb());
             ta.norm();
             tb.add(&y.a.getb());
             tb.norm();
-            let mut tc = FP2::new_copy(&ta);
+            let mut tc = ta.clone();
             tc.mul(&tb);
-            let mut t = FP2::new_copy(&w1);
+            let mut t = w1.clone();
             t.add(&w2);
             t.neg();
             tc.add(&t);
 
-            ta.copy(&self.a.geta());
+            ta = self.a.geta();
             ta.add(&self.c.getb());
             ta.norm();
-            tb.copy(&y.a.geta());
+            tb = y.a.geta();
             tb.add(&y.c.getb());
             tb.norm();
-            let mut td = FP2::new_copy(&ta);
+            let mut td = ta.clone();
             td.mul(&tb);
-            t.copy(&w1);
+            t = w1.clone();
             t.add(&w3);
             t.neg();
             td.add(&t);
 
-            ta.copy(&self.a.getb());
+            ta = self.a.getb();
             ta.add(&self.c.getb());
             ta.norm();
-            tb.copy(&y.a.getb());
+            tb = y.a.getb();
             tb.add(&y.c.getb());
             tb.norm();
-            let mut te = FP2::new_copy(&ta);
+            let mut te = ta.clone();
             te.mul(&tb);
-            t.copy(&w2);
+            t = w2.clone();
             t.add(&w3);
             t.neg();
             te.add(&t);
@@ -733,10 +698,9 @@ impl FP12 {
 
     /* self=1/self */
     pub fn inverse(&mut self) {
-        let mut f0 = FP4::new_copy(&self.a);
-        let mut f1 = FP4::new_copy(&self.b);
-        let mut f2 = FP4::new_copy(&self.a);
-        let mut f3 = FP4::new();
+        let mut f0 = self.geta();
+        let mut f1 = self.getb();
+        let mut f2 = self.geta();
 
         self.norm();
         f0.sqr();
@@ -745,21 +709,21 @@ impl FP12 {
         f0.sub(&f1);
         f0.norm();
 
-        f1.copy(&self.c);
+        f1 = self.getc();
         f1.sqr();
         f1.times_i();
         f2.mul(&self.b);
         f1.sub(&f2);
         f1.norm();
 
-        f2.copy(&self.b);
+        f2 = self.getb();
         f2.sqr();
-        f3.copy(&self.a);
+        let mut f3 = self.geta();
         f3.mul(&self.c);
         f2.sub(&f3);
         f2.norm();
 
-        f3.copy(&self.b);
+        f3 = self.getb();
         f3.mul(&f2);
         f3.times_i();
         self.a.mul(&f0);
@@ -770,19 +734,19 @@ impl FP12 {
         f3.add(&self.c);
         f3.norm();
         f3.inverse();
-        self.a.copy(&f0);
+        self.a = f0.clone();
         self.a.mul(&f3);
-        self.b.copy(&f1);
+        self.b = f1.clone();
         self.b.mul(&f3);
-        self.c.copy(&f2);
+        self.c = f2.clone();
         self.c.mul(&f3);
         self.stype = DENSE;
     }
 
     /* self=self^p using Frobenius */
     pub fn frob(&mut self, f: &FP2) {
-        let mut f2 = FP2::new_copy(f);
-        let mut f3 = FP2::new_copy(f);
+        let mut f2 = f.clone();
+        let mut f3 = f.clone();
 
         f2.sqr();
         f3.mul(&f2);
@@ -798,8 +762,7 @@ impl FP12 {
 
     /* trace function */
     pub fn trace(&mut self) -> FP4 {
-        let mut t = FP4::new();
-        t.copy(&self.a);
+        let mut t = self.geta();
         t.imul(3);
         t.reduce();
         return t;
@@ -813,71 +776,71 @@ impl FP12 {
         for i in 0..mb {
             t[i] = w[i]
         }
-        let mut a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + mb]
         }
-        let mut b = Big::frombytes(&t);
-        let mut c = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 2 * mb]
         }
-        a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 3 * mb]
         }
-        b = Big::frombytes(&t);
-        let mut d = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        let e = FP4::new_fp2s(&c, &d);
+        let e = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 4 * mb]
         }
-        a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 5 * mb]
         }
-        b = Big::frombytes(&t);
-        c = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 6 * mb]
         }
-        a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 7 * mb]
         }
-        b = Big::frombytes(&t);
-        d = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        let f = FP4::new_fp2s(&c, &d);
+        let f = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 8 * mb]
         }
-        a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 9 * mb]
         }
-        b = Big::frombytes(&t);
+        let b = Big::frombytes(&t);
 
-        c = FP2::new_bigs(&a, &b);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 10 * mb]
         }
-        a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 11 * mb]
         }
-        b = Big::frombytes(&t);
-        d = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        let g = FP4::new_fp2s(&c, &d);
+        let g = FP4::new_fp2s(c, d);
 
-        return FP12::new_fp4s(&e, &f, &g);
+        FP12::new_fp4s(e, f, g)
     }
 
     /* convert this to byte array */
@@ -972,14 +935,14 @@ impl FP12 {
 
     /* self=self^e */
     pub fn pow(&self, e: &Big) -> FP12 {
-        let mut r = FP12::new_copy(self);
+        let mut r = self.clone();
         r.norm();
-        let mut e1 = Big::new_copy(e);
+        let mut e1 = e.clone();
         e1.norm();
-        let mut e3 = Big::new_copy(&e1);
+        let mut e3 = e1.clone();
         e3.pmul(3);
         e3.norm();
-        let mut w = FP12::new_copy(&r);
+        let mut w = r.clone();
 
         let nb = e3.nbits();
         for i in (1..nb - 1).rev() {
@@ -1001,32 +964,31 @@ impl FP12 {
 
     /* constant time powering by small integer of max length bts */
     pub fn pinpow(&mut self, e: i32, bts: i32) {
-        let mut r: [FP12; 2] = [FP12::new_int(1), FP12::new_copy(self)];
-        let mut t = FP12::new();
+        let mut r: [FP12; 2] = [FP12::new_int(1), self.clone()];
 
         for i in (0..bts).rev() {
             let b: usize = ((e >> i) & 1) as usize;
-            t.copy(&r[b]);
+            let t = r[b].clone();
             r[1 - b].mul(&t);
             r[b].usqr();
         }
-        self.copy(&r[0]);
+        *self = r[0].clone();
     }
 
     pub fn compow(&mut self, e: &Big, r: &Big) -> FP4 {
-        let f = FP2::new_bigs(&Big::new_ints(&rom::FRA), &Big::new_ints(&rom::FRB));
+        let f = FP2::new_bigs(Big::new_ints(&rom::FRA), Big::new_ints(&rom::FRB));
         let q = Big::new_ints(&rom::MODULUS);
 
-        let mut g1 = FP12::new_copy(self);
-        let mut g2 = FP12::new_copy(self);
+        let mut g1 = self.clone();
+        let mut g2 = self.clone();
 
-        let mut m = Big::new_copy(&q);
+        let mut m = q.clone();
         m.rmod(&r);
 
-        let mut a = Big::new_copy(&e);
+        let mut a = e.clone();
         a.rmod(&m);
 
-        let mut b = Big::new_copy(&e);
+        let mut b = e.clone();
         b.div(&m);
 
         let mut c = g1.trace();
@@ -1065,45 +1027,39 @@ impl FP12 {
             FP12::new(),
         ];
 
-        let mut r = FP12::new();
         let mut p = FP12::new();
         const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize);
         let mut w: [i8; CT] = [0; CT];
         let mut s: [i8; CT] = [0; CT];
 
         let mut mt = Big::new();
-        let mut t: [Big; 4] = [
-            Big::new_copy(&u[0]),
-            Big::new_copy(&u[1]),
-            Big::new_copy(&u[2]),
-            Big::new_copy(&u[3]),
-        ];
+        let mut t: [Big; 4] = [u[0].clone(), u[1].clone(), u[2].clone(), u[3].clone()];
 
         for i in 0..4 {
             t[i].norm();
         }
 
         // precomputation
-        g[0].copy(&q[0]);
-        r.copy(&g[0]);
-        g[1].copy(&r);
+        g[0] = q[0].clone();
+        let mut r = g[0].clone();
+        g[1] = r.clone();
         g[1].mul(&q[1]); // q[0].q[1]
-        g[2].copy(&r);
+        g[2] = r.clone();
         g[2].mul(&q[2]);
-        r.copy(&g[1]); // q[0].q[2]
-        g[3].copy(&r);
+        r = g[1].clone(); // q[0].q[2]
+        g[3] = r.clone();
         g[3].mul(&q[2]);
-        r.copy(&g[0]); // q[0].q[1].q[2]
-        g[4].copy(&r);
+        r = g[0].clone(); // q[0].q[1].q[2]
+        g[4] = r.clone();
         g[4].mul(&q[3]);
-        r.copy(&g[1]); // q[0].q[3]
-        g[5].copy(&r);
+        r = g[1].clone(); // q[0].q[3]
+        g[5] = r.clone();
         g[5].mul(&q[3]);
-        r.copy(&g[2]); // q[0].q[1].q[3]
-        g[6].copy(&r);
+        r = g[2].clone(); // q[0].q[1].q[3]
+        g[6] = r.clone();
         g[6].mul(&q[3]);
-        r.copy(&g[3]); // q[0].q[2].q[3]
-        g[7].copy(&r);
+        r = g[3].clone(); // q[0].q[2].q[3]
+        g[7] = r.clone();
         g[7].mul(&q[3]); // q[0].q[1].q[2].q[3]
 
         // Make it odd
@@ -1150,7 +1106,7 @@ impl FP12 {
         }
 
         // apply correction
-        r.copy(&q[0]);
+        r = q[0].clone();
         r.conj();
         r.mul(&p);
         p.cmove(&r, pb);
diff --git a/src/fp16.rs b/src/fp16.rs
index d650771..be9e12d 100644
--- a/src/fp16.rs
+++ b/src/fp16.rs
@@ -22,7 +22,7 @@ use super::fp2::FP2;
 use super::fp8::FP8;
 //use std::str::SplitWhitespace;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct FP16 {
     a: FP8,
     b: FP8,
@@ -37,45 +37,32 @@ impl FP16 {
     }
 
     pub fn new_int(a: isize) -> FP16 {
-        let mut f = FP16::new();
-        f.a.copy(&FP8::new_int(a));
-        f.b.zero();
-        return f;
-    }
-
-    pub fn new_copy(x: &FP16) -> FP16 {
-        let mut f = FP16::new();
-        f.a.copy(&x.a);
-        f.b.copy(&x.b);
-        return f;
+        FP16 {
+            a: FP8::new_int(a),
+            b: FP8::new(),
+        }
     }
 
-    pub fn new_fp8s(c: &FP8, d: &FP8) -> FP16 {
-        let mut f = FP16::new();
-        f.a.copy(c);
-        f.b.copy(d);
-        return f;
+    pub fn new_fp8s(a: FP8, b: FP8) -> FP16 {
+        FP16 { a, b }
     }
 
-    pub fn new_fp8(c: &FP8) -> FP16 {
-        let mut f = FP16::new();
-        f.a.copy(c);
-        f.b.zero();
-        return f;
+    pub fn new_fp8(a: FP8) -> FP16 {
+        FP16 { a, b: FP8::new() }
     }
 
     pub fn set_fp8s(&mut self, c: &FP8, d: &FP8) {
-        self.a.copy(&c);
-        self.b.copy(&d);
+        self.a = c.clone();
+        self.b = d.clone();
     }
 
     pub fn set_fp8(&mut self, c: &FP8) {
-        self.a.copy(&c);
+        self.a = c.clone();
         self.b.zero();
     }
 
     pub fn set_fp8h(&mut self, c: &FP8) {
-        self.b.copy(&c);
+        self.b = c.clone();
         self.a.zero();
     }
 
@@ -107,37 +94,29 @@ impl FP16 {
         return self.a.equals(&one) && self.b.iszilch();
     }
 
-    /* test is w real? That is in a+ib test b is zero */
+    /// Test is w real? That is in a+ib test b is zero */
     pub fn isreal(&self) -> bool {
         return self.b.iszilch();
     }
-    /* extract real part a */
+
+    /// Extract real part a
     pub fn real(&self) -> FP8 {
-        let f = FP8::new_copy(&self.a);
-        return f;
+        self.geta()
     }
 
     pub fn geta(&self) -> FP8 {
-        return self.a;
-        //        let f = FP8::new_copy(&self.a);
-        //        return f;
+        self.a.clone()
     }
-    /* extract imaginary part b */
+
+    /// Extract imaginary part b
     pub fn getb(&self) -> FP8 {
-        return self.b;
-        //        let f = FP8::new_copy(&self.b);
-        //        return f;
+        self.b.clone()
     }
 
     /* test self=x */
     pub fn equals(&self, x: &FP16) -> bool {
         return self.a.equals(&x.a) && self.b.equals(&x.b);
     }
-    /* copy self=x */
-    pub fn copy(&mut self, x: &FP16) {
-        self.a.copy(&x.a);
-        self.b.copy(&x.b);
-    }
 
     /* set self=0 */
     pub fn zero(&mut self) {
@@ -154,16 +133,15 @@ impl FP16 {
     /* negate self mod Modulus */
     pub fn neg(&mut self) {
         self.norm();
-        let mut m = FP8::new_copy(&self.a);
-        let mut t = FP8::new();
+        let mut m = self.geta();
 
         m.add(&self.b);
         m.neg();
-        t.copy(&m);
+        let mut t = m.clone();
         t.add(&self.b);
-        self.b.copy(&m);
+        self.b = m.clone();
         self.b.add(&self.a);
-        self.a.copy(&t);
+        self.a = t.clone();
         self.norm();
     }
 
@@ -196,7 +174,7 @@ impl FP16 {
 
     /* self-=a */
     pub fn sub(&mut self, x: &FP16) {
-        let mut m = FP16::new_copy(x);
+        let mut m = x.clone();
         m.neg();
         self.add(&m);
     }
@@ -228,9 +206,9 @@ impl FP16 {
     /* self*=self */
 
     pub fn sqr(&mut self) {
-        let mut t1 = FP8::new_copy(&self.a);
-        let mut t2 = FP8::new_copy(&self.b);
-        let mut t3 = FP8::new_copy(&self.a);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
+        let mut t3 = self.geta();
 
         t3.mul(&self.b);
         t1.add(&self.b);
@@ -241,11 +219,11 @@ impl FP16 {
         t1.norm();
         t2.norm();
 
-        self.a.copy(&t1);
+        self.a = t1.clone();
 
         self.a.mul(&t2);
 
-        t2.copy(&t3);
+        t2 = t3.clone();
         t2.times_i();
         t2.add(&t3);
         t2.norm();
@@ -253,21 +231,20 @@ impl FP16 {
         self.a.add(&t2);
 
         t3.dbl();
-        self.b.copy(&t3);
+        self.b = t3.clone();
 
         self.norm();
     }
 
     /* self*=y */
     pub fn mul(&mut self, y: &FP16) {
-        let mut t1 = FP8::new_copy(&self.a);
-        let mut t2 = FP8::new_copy(&self.b);
-        let mut t3 = FP8::new();
-        let mut t4 = FP8::new_copy(&self.b);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
+        let mut t3 = y.getb();
+        let mut t4 = self.getb();
 
         t1.mul(&y.a);
         t2.mul(&y.b);
-        t3.copy(&y.b);
         t3.add(&y.a);
         t4.add(&self.a);
 
@@ -276,18 +253,18 @@ impl FP16 {
 
         t4.mul(&t3);
 
-        t3.copy(&t1);
+        t3 = t1.clone();
         t3.neg();
         t4.add(&t3);
         t4.norm();
 
-        t3.copy(&t2);
+        t3 = t2.clone();
         t3.neg();
-        self.b.copy(&t4);
+        self.b = t4.clone();
         self.b.add(&t3);
 
         t2.times_i();
-        self.a.copy(&t2);
+        self.a = t2.clone();
         self.a.add(&t1);
 
         self.norm();
@@ -300,8 +277,8 @@ impl FP16 {
 
     /* self=1/self */
     pub fn inverse(&mut self) {
-        let mut t1 = FP8::new_copy(&self.a);
-        let mut t2 = FP8::new_copy(&self.b);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
 
         t1.sqr();
         t2.sqr();
@@ -318,11 +295,11 @@ impl FP16 {
 
     /* self*=i where i = sqrt(-1+sqrt(-1)) */
     pub fn times_i(&mut self) {
-        let mut s = FP8::new_copy(&self.b);
-        let t = FP8::new_copy(&self.a);
+        let mut s = self.getb();
+        let t = self.geta();
         s.times_i();
-        self.a.copy(&s);
-        self.b.copy(&t);
+        self.a = s.clone();
+        self.b = t.clone();
 
         self.norm();
     }
@@ -339,7 +316,7 @@ impl FP16 {
 
     /* self=self^p using Frobenius */
     pub fn frob(&mut self, f: &FP2) {
-        let mut ff = FP2::new_copy(f);
+        let mut ff = f.clone();
         ff.sqr();
         ff.norm();
         self.a.frob(&ff);
@@ -350,9 +327,9 @@ impl FP16 {
 
     /* self=self^e */
     pub fn pow(&self, e: &Big) -> FP16 {
-        let mut w = FP16::new_copy(self);
+        let mut w = self.clone();
         w.norm();
-        let mut z = Big::new_copy(&e);
+        let mut z = e.clone();
         let mut r = FP16::new_int(1);
         z.norm();
         loop {
@@ -372,8 +349,8 @@ impl FP16 {
 
     /* XTR xtr_a function */
     pub fn xtr_a(&mut self, w: &FP16, y: &FP16, z: &FP16) {
-        let mut r = FP16::new_copy(w);
-        let mut t = FP16::new_copy(w);
+        let mut r = w.clone();
+        let mut t = w.clone();
         r.sub(y);
         r.norm();
         r.pmul(&self.a);
@@ -382,7 +359,7 @@ impl FP16 {
         t.pmul(&self.b);
         t.times_i();
 
-        self.copy(&r);
+        *self = r.clone();
         self.add(&t);
         self.add(z);
 
@@ -391,7 +368,7 @@ impl FP16 {
 
     /* XTR xtr_d function */
     pub fn xtr_d(&mut self) {
-        let mut w = FP16::new_copy(self);
+        let mut w = self.clone();
         self.sqr();
         w.conj();
         w.dbl();
@@ -402,17 +379,15 @@ impl FP16 {
 
     /* r=x^n using XTR method on traces of FP24s */
     pub fn xtr_pow(&self, n: &Big) -> FP16 {
-        let mut sf = FP16::new_copy(self);
+        let mut sf = self.clone();
         sf.norm();
         let mut a = FP16::new_int(3);
-        let mut b = FP16::new_copy(&sf);
-        let mut c = FP16::new_copy(&b);
+        let mut b = sf.clone();
+        let mut c = b.clone();
         c.xtr_d();
-        let mut t = FP16::new();
-        let mut r = FP16::new();
 
         let par = n.parity();
-        let mut v = Big::new_copy(n);
+        let mut v = n.clone();
         v.norm();
         v.fshr(1);
         if par == 0 {
@@ -423,46 +398,39 @@ impl FP16 {
         let nb = v.nbits();
         for i in (0..nb).rev() {
             if v.bit(i) != 1 {
-                t.copy(&b);
+                let t = b.clone();
                 sf.conj();
                 c.conj();
                 b.xtr_a(&a, &sf, &c);
                 sf.conj();
-                c.copy(&t);
+                c = t.clone();
                 c.xtr_d();
                 a.xtr_d();
             } else {
-                t.copy(&a);
+                let mut t = a.clone();
                 t.conj();
-                a.copy(&b);
+                a = b.clone();
                 a.xtr_d();
                 b.xtr_a(&c, &sf, &t);
                 c.xtr_d();
             }
         }
-        if par == 0 {
-            r.copy(&c)
-        } else {
-            r.copy(&b)
-        }
+        let mut r = if par == 0 { c } else { b };
         r.reduce();
-        return r;
+        r
     }
 
     /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
     pub fn xtr_pow2(&mut self, ck: &FP16, ckml: &FP16, ckm2l: &FP16, a: &Big, b: &Big) -> FP16 {
-        let mut e = Big::new_copy(a);
-        let mut d = Big::new_copy(b);
-        let mut w = Big::new();
+        let mut e = a.clone();
+        let mut d = b.clone();
         d.norm();
         e.norm();
 
-        let mut cu = FP16::new_copy(ck); // can probably be passed in w/o copying
-        let mut cv = FP16::new_copy(self);
-        let mut cumv = FP16::new_copy(ckml);
-        let mut cum2v = FP16::new_copy(ckm2l);
-        let mut r = FP16::new();
-        let mut t = FP16::new();
+        let mut cu = ck.clone(); // can probably be passed in w/o copying
+        let mut cv = self.clone();
+        let mut cumv = ckml.clone();
+        let mut cum2v = ckm2l.clone();
 
         let mut f2: usize = 0;
         while d.parity() == 0 && e.parity() == 0 {
@@ -473,130 +441,129 @@ impl FP16 {
 
         while Big::comp(&d, &e) != 0 {
             if Big::comp(&d, &e) > 0 {
-                w.copy(&e);
+                let mut w = e.clone();
                 w.imul(4);
                 w.norm();
                 if Big::comp(&d, &w) <= 0 {
-                    w.copy(&d);
-                    d.copy(&e);
+                    w = d.clone();
+                    d = e.clone();
                     e.rsub(&w);
                     e.norm();
 
-                    t.copy(&cv);
+                    let mut t = cv.clone();
                     t.xtr_a(&cu, &cumv, &cum2v);
-                    cum2v.copy(&cumv);
+                    cum2v = cumv.clone();
                     cum2v.conj();
-                    cumv.copy(&cv);
-                    cv.copy(&cu);
-                    cu.copy(&t);
+                    cumv = cv.clone();
+                    cv = cu.clone();
+                    cu = t.clone();
                 } else {
                     if d.parity() == 0 {
                         d.fshr(1);
-                        r.copy(&cum2v);
+                        let mut r = cum2v.clone();
                         r.conj();
-                        t.copy(&cumv);
+                        let mut t = cumv.clone();
                         t.xtr_a(&cu, &cv, &r);
-                        cum2v.copy(&cumv);
+                        cum2v = cumv.clone();
                         cum2v.xtr_d();
-                        cumv.copy(&t);
+                        cumv = t.clone();
                         cu.xtr_d();
                     } else {
                         if e.parity() == 1 {
                             d.sub(&e);
                             d.norm();
                             d.fshr(1);
-                            t.copy(&cv);
+                            let mut t = cv.clone();
                             t.xtr_a(&cu, &cumv, &cum2v);
                             cu.xtr_d();
-                            cum2v.copy(&cv);
+                            cum2v = cv.clone();
                             cum2v.xtr_d();
                             cum2v.conj();
-                            cv.copy(&t);
+                            cv = t.clone();
                         } else {
-                            w.copy(&d);
-                            d.copy(&e);
+                            w = d.clone();
+                            d = e.clone();
                             d.fshr(1);
-                            e.copy(&w);
-                            t.copy(&cumv);
+                            e = w.clone();
+                            let mut t = cumv.clone();
                             t.xtr_d();
-                            cumv.copy(&cum2v);
+                            cumv = cum2v.clone();
                             cumv.conj();
-                            cum2v.copy(&t);
+                            cum2v = t.clone();
                             cum2v.conj();
-                            t.copy(&cv);
+                            t = cv.clone();
                             t.xtr_d();
-                            cv.copy(&cu);
-                            cu.copy(&t);
+                            cv = cu.clone();
+                            cu = t.clone();
                         }
                     }
                 }
             }
             if Big::comp(&d, &e) < 0 {
-                w.copy(&d);
+                let mut w = d.clone();
                 w.imul(4);
                 w.norm();
                 if Big::comp(&e, &w) <= 0 {
                     e.sub(&d);
                     e.norm();
-                    t.copy(&cv);
+                    let mut t = cv.clone();
                     t.xtr_a(&cu, &cumv, &cum2v);
-                    cum2v.copy(&cumv);
-                    cumv.copy(&cu);
-                    cu.copy(&t);
+                    cum2v = cumv.clone();
+                    cumv = cu.clone();
+                    cu = t;
                 } else {
                     if e.parity() == 0 {
-                        w.copy(&d);
-                        d.copy(&e);
+                        w = d.clone();
+                        d = e.clone();
                         d.fshr(1);
-                        e.copy(&w);
-                        t.copy(&cumv);
+                        e = w.clone();
+                        let mut t = cumv.clone();
                         t.xtr_d();
-                        cumv.copy(&cum2v);
+                        cumv = cum2v.clone();
                         cumv.conj();
-                        cum2v.copy(&t);
+                        cum2v = t;
                         cum2v.conj();
-                        t.copy(&cv);
+                        t = cv.clone();
                         t.xtr_d();
-                        cv.copy(&cu);
-                        cu.copy(&t);
+                        cv = cu.clone();
+                        cu = t;
                     } else {
                         if d.parity() == 1 {
-                            w.copy(&e);
-                            e.copy(&d);
+                            w = e.clone();
+                            e = d.clone();
                             w.sub(&d);
                             w.norm();
-                            d.copy(&w);
+                            d = w.clone();
                             d.fshr(1);
-                            t.copy(&cv);
+                            let mut t = cv.clone();
                             t.xtr_a(&cu, &cumv, &cum2v);
                             cumv.conj();
-                            cum2v.copy(&cu);
+                            cum2v = cu.clone();
                             cum2v.xtr_d();
                             cum2v.conj();
-                            cu.copy(&cv);
+                            cu = cv.clone();
                             cu.xtr_d();
-                            cv.copy(&t);
+                            cv = t;
                         } else {
                             d.fshr(1);
-                            r.copy(&cum2v);
+                            let mut r = cum2v.clone();
                             r.conj();
-                            t.copy(&cumv);
+                            let mut t = cumv.clone();
                             t.xtr_a(&cu, &cv, &r);
-                            cum2v.copy(&cumv);
+                            cum2v = cumv.clone();
                             cum2v.xtr_d();
-                            cumv.copy(&t);
+                            cumv = t.clone();
                             cu.xtr_d();
                         }
                     }
                 }
             }
         }
-        r.copy(&cv);
+        let mut r = cv;
         r.xtr_a(&cu, &cumv, &cum2v);
         for _ in 0..f2 {
             r.xtr_d()
         }
-        r = r.xtr_pow(&mut d);
-        return r;
+        r.xtr_pow(&mut d)
     }
 }
diff --git a/src/fp2.rs b/src/fp2.rs
index 87a0db1..84a6c85 100644
--- a/src/fp2.rs
+++ b/src/fp2.rs
@@ -25,7 +25,7 @@ use super::rom;
 use std::fmt;
 use std::str::SplitWhitespace;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct FP2 {
     a: FP,
     b: FP,
@@ -58,45 +58,32 @@ impl FP2 {
     }
 
     pub fn new_int(a: isize) -> FP2 {
-        let mut f = FP2::new();
-        f.a.copy(&FP::new_int(a));
-        f.b.zero();
-        return f;
-    }
-
-    pub fn new_copy(x: &FP2) -> FP2 {
-        let mut f = FP2::new();
-        f.a.copy(&x.a);
-        f.b.copy(&x.b);
-        return f;
+        FP2 {
+            a: FP::new_int(a),
+            b: FP::new(),
+        }
     }
 
-    pub fn new_fps(c: &FP, d: &FP) -> FP2 {
-        let mut f = FP2::new();
-        f.a.copy(c);
-        f.b.copy(d);
-        return f;
+    pub fn new_fps(a: FP, b: FP) -> FP2 {
+        FP2 { a, b }
     }
 
-    pub fn new_bigs(c: &Big, d: &Big) -> FP2 {
-        let mut f = FP2::new();
-        f.a.copy(&FP::new_big(c));
-        f.b.copy(&FP::new_big(d));
-        return f;
+    pub fn new_bigs(c: Big, d: Big) -> FP2 {
+        FP2 {
+            a: FP::new_big(c),
+            b: FP::new_big(d),
+        }
     }
 
-    pub fn new_fp(c: &FP) -> FP2 {
-        let mut f = FP2::new();
-        f.a.copy(c);
-        f.b.zero();
-        return f;
+    pub fn new_fp(a: FP) -> FP2 {
+        FP2 { a, b: FP::new() }
     }
 
-    pub fn new_big(c: &Big) -> FP2 {
-        let mut f = FP2::new();
-        f.a.copy(&FP::new_big(c));
-        f.b.zero();
-        return f;
+    pub fn new_big(c: Big) -> FP2 {
+        FP2 {
+            a: FP::new_big(c),
+            b: FP::new(),
+        }
     }
 
     /* reduce components mod Modulus */
@@ -142,12 +129,6 @@ impl FP2 {
         return self.b.redc();
     }
 
-    /* copy self=x */
-    pub fn copy(&mut self, x: &FP2) {
-        self.a.copy(&x.a);
-        self.b.copy(&x.b);
-    }
-
     /* set self=0 */
     pub fn zero(&mut self) {
         self.a.zero();
@@ -162,16 +143,14 @@ impl FP2 {
 
     /* negate self mod Modulus */
     pub fn neg(&mut self) {
-        let mut m = FP::new_copy(&self.a);
-        let mut t = FP::new();
-
+        let mut m = self.a.clone();
         m.add(&self.b);
         m.neg();
-        t.copy(&m);
+        let mut t = m.clone();
         t.add(&self.b);
-        self.b.copy(&m);
+        self.b = m;
         self.b.add(&self.a);
-        self.a.copy(&t);
+        self.a = t;
     }
 
     /* set to a-ib */
@@ -193,7 +172,7 @@ impl FP2 {
 
     /* self-=a */
     pub fn sub(&mut self, x: &FP2) {
-        let mut m = FP2::new_copy(x);
+        let mut m = x.clone();
         m.neg();
         self.add(&m);
     }
@@ -218,9 +197,9 @@ impl FP2 {
 
     /* self*=self */
     pub fn sqr(&mut self) {
-        let mut w1 = FP::new_copy(&self.a);
-        let mut w3 = FP::new_copy(&self.a);
-        let mut mb = FP::new_copy(&self.b);
+        let mut w1 = self.a.clone();
+        let mut w3 = self.a.clone();
+        let mut mb = self.b.clone();
 
         w1.add(&self.b);
 
@@ -255,8 +234,8 @@ impl FP2 {
 
         pr.ucopy(&p);
 
-        let mut c = Big::new_copy(&(self.a.x));
-        let mut d = Big::new_copy(&(y.a.x));
+        let mut c = self.a.x.clone();
+        let mut d = y.a.x.clone();
 
         let mut a = Big::mul(&self.a.x, &y.a.x);
         let mut b = Big::mul(&self.b.x, &y.b.x);
@@ -267,7 +246,7 @@ impl FP2 {
         d.norm();
 
         let mut e = Big::mul(&c, &d);
-        let mut f = DBig::new_copy(&a);
+        let mut f = a.clone();
         f.add(&b);
         b.rsub(&pr);
 
@@ -276,9 +255,9 @@ impl FP2 {
         e.sub(&f);
         e.norm();
 
-        self.a.x.copy(&FP::modulo(&mut a));
+        self.a.x = FP::modulo(&mut a);
         self.a.xes = 3;
-        self.b.x.copy(&FP::modulo(&mut e));
+        self.b.x = FP::modulo(&mut e);
         self.b.xes = 2;
     }
 
@@ -288,8 +267,8 @@ impl FP2 {
         if self.iszilch() {
             return true;
         }
-        let mut w1 = FP::new_copy(&self.b);
-        let mut w2 = FP::new_copy(&self.a);
+        let mut w1 = self.b.clone();
+        let mut w2 = self.a.clone();
         w1.sqr();
         w2.sqr();
         w1.add(&w2);
@@ -297,14 +276,14 @@ impl FP2 {
             self.zero();
             return false;
         }
-        w2.copy(&w1.sqrt());
-        w1.copy(&w2);
-        w2.copy(&self.a);
+        w2 = w1.sqrt();
+        w1 = w2.clone();
+        w2 = self.a.clone();
         w2.add(&w1);
         w2.norm();
         w2.div2();
         if w2.jacobi() != 1 {
-            w2.copy(&self.a);
+            w2 = self.a.clone();
             w2.sub(&w1);
             w2.norm();
             w2.div2();
@@ -313,8 +292,8 @@ impl FP2 {
                 return false;
             }
         }
-        w1.copy(&w2.sqrt());
-        self.a.copy(&w1);
+        w1 = w2.sqrt();
+        self.a = w1.clone();
         w1.dbl();
         w1.inverse();
         self.b.mul(&w1);
@@ -345,8 +324,8 @@ impl FP2 {
     /* self=1/self */
     pub fn inverse(&mut self) {
         self.norm();
-        let mut w1 = FP::new_copy(&self.a);
-        let mut w2 = FP::new_copy(&self.b);
+        let mut w1 = self.a.clone();
+        let mut w2 = self.b.clone();
 
         w1.sqr();
         w2.sqr();
@@ -366,44 +345,44 @@ impl FP2 {
 
     /* self*=sqrt(-1) */
     pub fn times_i(&mut self) {
-        let z = FP::new_copy(&self.a);
-        self.a.copy(&self.b);
+        let z = self.a.clone();
+        self.a = self.b.clone();
         self.a.neg();
-        self.b.copy(&z);
+        self.b = z;
     }
 
     /* w*=(1+sqrt(-1)) */
     /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
     pub fn mul_ip(&mut self) {
-        let t = FP2::new_copy(self);
-        let z = FP::new_copy(&self.a);
-        self.a.copy(&self.b);
+        let t = self.clone();
+        let z = self.a.clone();
+        self.a = self.b.clone();
         self.a.neg();
-        self.b.copy(&z);
+        self.b = z.clone();
         self.add(&t);
     }
 
     pub fn div_ip2(&mut self) {
         let mut t = FP2::new();
         self.norm();
-        t.a.copy(&self.a);
+        t.a = self.a.clone();
         t.a.add(&self.b);
-        t.b.copy(&self.b);
+        t.b = self.b.clone();
         t.b.sub(&self.a);
         t.norm();
-        self.copy(&t);
+        *self = t;
     }
 
     /* w/=(1+sqrt(-1)) */
     pub fn div_ip(&mut self) {
         let mut t = FP2::new();
         self.norm();
-        t.a.copy(&self.a);
+        t.a = self.a.clone();
         t.a.add(&self.b);
-        t.b.copy(&self.b);
+        t.b = self.b.clone();
         t.b.sub(&self.a);
         t.norm();
-        self.copy(&t);
+        *self = t;
         self.div2();
     }
 }
diff --git a/src/fp24.rs b/src/fp24.rs
index 12cd1ab..5a74ac1 100644
--- a/src/fp24.rs
+++ b/src/fp24.rs
@@ -33,7 +33,7 @@ pub const SPARSER: usize = 2;
 pub const SPARSE: usize = 3;
 pub const DENSE: usize = 4;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct FP24 {
     a: FP8,
     b: FP8,
@@ -60,43 +60,32 @@ impl FP24 {
     }
 
     pub fn new_int(a: isize) -> FP24 {
-        let mut f = FP24::new();
-        f.a.copy(&FP8::new_int(a));
-        f.b.zero();
-        f.c.zero();
-        if a == 1 {
-            f.stype = ONE;
-        } else {
-            f.stype = SPARSER;
-        }
-        return f;
-    }
+        let stype = if a == 1 { ONE } else { SPARSER };
 
-    pub fn new_copy(x: &FP24) -> FP24 {
-        let mut f = FP24::new();
-        f.a.copy(&x.a);
-        f.b.copy(&x.b);
-        f.c.copy(&x.c);
-        f.stype = x.stype;
-        return f;
+        FP24 {
+            a: FP8::new_int(a),
+            b: FP8::new(),
+            c: FP8::new(),
+            stype,
+        }
     }
 
-    pub fn new_fp8s(d: &FP8, e: &FP8, f: &FP8) -> FP24 {
-        let mut g = FP24::new();
-        g.a.copy(d);
-        g.b.copy(e);
-        g.c.copy(f);
-        g.stype = DENSE;
-        return g;
+    pub fn new_fp8s(a: FP8, b: FP8, c: FP8) -> FP24 {
+        FP24 {
+            a,
+            b,
+            c,
+            stype: DENSE,
+        }
     }
 
-    pub fn new_fp8(d: &FP8) -> FP24 {
-        let mut g = FP24::new();
-        g.a.copy(d);
-        g.b.zero();
-        g.c.zero();
-        g.stype = SPARSER;
-        return g;
+    pub fn new_fp8(a: FP8) -> FP24 {
+        FP24 {
+            a,
+            b: FP8::new(),
+            c: FP8::new(),
+            stype: SPARSER,
+        }
     }
 
     /* reduce components mod Modulus */
@@ -151,7 +140,7 @@ impl FP24 {
         self.cmove(&g[6], FP24::teq(babs, 6));
         self.cmove(&g[7], FP24::teq(babs, 7));
 
-        let mut invf = FP24::new_copy(self);
+        let mut invf = self.clone();
         invf.conj();
         self.cmove(&invf, (m & 1) as isize);
     }
@@ -168,23 +157,15 @@ impl FP24 {
     }
 
     pub fn geta(&self) -> FP8 {
-        return self.a;
+        self.a.clone()
     }
 
     pub fn getb(&self) -> FP8 {
-        return self.b;
+        self.b.clone()
     }
 
     pub fn getc(&self) -> FP8 {
-        return self.c;
-    }
-
-    /* copy self=x */
-    pub fn copy(&mut self, x: &FP24) {
-        self.a.copy(&x.a);
-        self.b.copy(&x.b);
-        self.c.copy(&x.c);
-        self.stype = x.stype;
+        self.c.clone()
     }
 
     /* set self=1 */
@@ -212,13 +193,12 @@ impl FP24 {
 
     /* Granger-Scott Unitary Squaring */
     pub fn usqr(&mut self) {
-        let mut a = FP8::new_copy(&self.a);
-        let mut b = FP8::new_copy(&self.c);
-        let mut c = FP8::new_copy(&self.b);
-        let mut d = FP8::new();
+        let mut a = self.geta();
+        let mut b = self.getc();
+        let mut c = self.getb();
 
         self.a.sqr();
-        d.copy(&self.a);
+        let mut d = self.geta();
         d.add(&self.a);
         self.a.add(&d);
 
@@ -230,13 +210,13 @@ impl FP24 {
         b.sqr();
         b.times_i();
 
-        d.copy(&b);
+        d = b.clone();
         d.add(&b);
         b.add(&d);
         b.norm();
 
         c.sqr();
-        d.copy(&c);
+        d = c.clone();
         d.add(&c);
         c.add(&d);
         c.norm();
@@ -257,10 +237,10 @@ impl FP24 {
         if self.stype == ONE {
             return;
         }
-        let mut a = FP8::new_copy(&self.a);
-        let mut b = FP8::new_copy(&self.b);
-        let mut c = FP8::new_copy(&self.c);
-        let mut d = FP8::new_copy(&self.a);
+        let mut a = self.geta();
+        let mut b = self.getb();
+        let mut c = self.getc();
+        let mut d = self.geta();
 
         a.sqr();
         b.mul(&self.c);
@@ -275,7 +255,7 @@ impl FP24 {
         self.c.norm();
         self.c.sqr();
 
-        self.a.copy(&a);
+        self.a = a.clone();
         a.add(&b);
         a.norm();
         a.add(&c);
@@ -288,7 +268,7 @@ impl FP24 {
 
         self.a.add(&b);
 
-        self.b.copy(&c);
+        self.b = c.clone();
         self.b.add(&d);
         self.c.add(&a);
         if self.stype == SPARSER {
@@ -301,12 +281,10 @@ impl FP24 {
 
     /* FP24 full multiplication self=self*y */
     pub fn mul(&mut self, y: &FP24) {
-        let mut z0 = FP8::new_copy(&self.a);
-        let mut z1 = FP8::new();
-        let mut z2 = FP8::new_copy(&mut self.b);
-        let mut z3 = FP8::new();
-        let mut t0 = FP8::new_copy(&self.a);
-        let mut t1 = FP8::new_copy(&y.a);
+        let mut z0 = self.geta();
+        let mut z2 = self.getb();
+        let mut t0 = self.geta();
+        let mut t1 = y.geta();
 
         z0.mul(&y.a);
         z2.mul(&y.b);
@@ -317,47 +295,47 @@ impl FP24 {
         t0.norm();
         t1.norm();
 
-        z1.copy(&t0);
+        let mut z1 = t0.clone();
         z1.mul(&t1);
-        t0.copy(&self.b);
+        t0 = self.getb();
         t0.add(&self.c);
-        t1.copy(&y.b);
+        t1 = y.getb();
         t1.add(&y.c);
 
         t0.norm();
         t1.norm();
 
-        z3.copy(&t0);
+        let mut z3 = t0.clone();
         z3.mul(&t1);
 
-        t0.copy(&z0);
+        t0 = z0.clone();
         t0.neg();
-        t1.copy(&z2);
+        t1 = z2.clone();
         t1.neg();
 
         z1.add(&t0);
         //z1.norm();
-        self.b.copy(&z1);
+        self.b = z1.clone();
         self.b.add(&t1);
 
         z3.add(&t1);
         z2.add(&t0);
 
-        t0.copy(&self.a);
+        t0 = self.geta();
         t0.add(&self.c);
         t0.norm();
-        t1.copy(&y.a);
+        t1 = y.geta();
         t1.add(&y.c);
         t1.norm();
         t0.mul(&t1);
         z2.add(&t0);
 
-        t0.copy(&self.c);
+        t0 = self.getc();
         t0.mul(&y.c);
-        t1.copy(&t0);
+        t1 = t0.clone();
         t1.neg();
 
-        self.c.copy(&z2);
+        self.c = z2.clone();
         self.c.add(&t1);
         z3.add(&t1);
         t0.times_i();
@@ -365,7 +343,7 @@ impl FP24 {
         z3.norm();
 
         z3.times_i();
-        self.a.copy(&z0);
+        self.a = z0.clone();
         self.a.add(&z3);
         self.stype = DENSE;
         self.norm();
@@ -376,80 +354,75 @@ impl FP24 {
     /* Usually w is denser than y */
     pub fn ssmul(&mut self, y: &FP24) {
         if self.stype == ONE {
-            self.copy(&y);
+            *self = y.clone();
             return;
         }
         if y.stype == ONE {
             return;
         }
         if y.stype >= SPARSE {
-            let mut z0 = FP8::new_copy(&self.a);
-            let mut z1 = FP8::new_int(0);
-            let mut z2 = FP8::new_int(0);
-            let mut z3 = FP8::new_int(0);
+            let mut z0 = self.geta();
+            let mut z2 = FP8::new();
             z0.mul(&y.a);
 
             if ecp::SEXTIC_TWIST == SexticTwist::MType {
                 if y.stype == SPARSE || self.stype == SPARSE {
-                    let mut ga = FP4::new_int(0);
-                    let mut gb = FP4::new_int(0);
-
-                    gb.copy(&self.b.getb());
+                    let mut gb = self.b.getb();
                     gb.mul(&y.b.getb());
-                    ga.zero();
+                    let mut ga = FP4::new();
                     if y.stype != SPARSE {
-                        ga.copy(&self.b.getb());
+                        ga = self.b.getb();
                         ga.mul(&y.b.geta());
                     }
                     if self.stype != SPARSE {
-                        ga.copy(&self.b.geta());
+                        ga = self.b.geta();
                         ga.mul(&y.b.getb());
                     }
                     z2.set_fp4s(&ga, &gb);
                     z2.times_i();
                 } else {
-                    z2.copy(&self.b);
+                    z2 = self.getb();
                     z2.mul(&y.b);
                 }
             } else {
-                z2.copy(&self.b);
+                z2 = self.getb();
                 z2.mul(&y.b);
             }
-            let mut t0 = FP8::new_copy(&self.a);
-            let mut t1 = FP8::new_copy(&y.a);
+            let mut t0 = self.geta();
+            let mut t1 = y.geta();
             t0.add(&self.b);
             t0.norm();
             t1.add(&y.b);
             t1.norm();
 
-            z1.copy(&t0);
+            let mut z1 = t0.clone();
             z1.mul(&t1);
-            t0.copy(&self.b);
+            t0 = self.getb();
             t0.add(&self.c);
             t0.norm();
-            t1.copy(&y.b);
+            t1 = y.getb();
             t1.add(&y.c);
             t1.norm();
 
-            z3.copy(&t0);
+            let mut z3 = t0.clone();
             z3.mul(&t1);
 
-            t0.copy(&z0);
+            t0 = z0.clone();
             t0.neg();
-            t1.copy(&z2);
+            t1 = z2.clone();
             t1.neg();
 
             z1.add(&t0);
-            self.b.copy(&z1);
+            self.b = z1.clone();
             self.b.add(&t1);
 
             z3.add(&t1);
             z2.add(&t0);
 
-            t0.copy(&self.a);
+            t0 = self.geta();
             t0.add(&self.c);
             t0.norm();
-            t1.copy(&y.a);
+            t1 = y.geta();
             t1.add(&y.c);
             t1.norm();
 
@@ -458,40 +431,37 @@ impl FP24 {
 
             if ecp::SEXTIC_TWIST == SexticTwist::DType {
                 if y.stype == SPARSE || self.stype == SPARSE {
-                    let mut ga = FP4::new_int(0);
-                    let mut gb = FP4::new_int(0);
-
-                    ga.copy(&self.c.geta());
+                    let mut ga = self.c.geta();
                     ga.mul(&y.c.geta());
-                    gb.zero();
+                    let mut gb = FP4::new();
                     if y.stype != SPARSE {
-                        gb.copy(&self.c.geta());
+                        gb = self.c.geta();
                         gb.mul(&y.c.getb());
                     }
                     if self.stype != SPARSE {
-                        gb.copy(&self.c.getb());
+                        gb = self.c.getb();
                         gb.mul(&y.c.geta());
                     }
                     t0.set_fp4s(&ga, &gb);
                 } else {
-                    t0.copy(&self.c);
+                    t0 = self.getc();
                     t0.mul(&y.c);
                 }
             } else {
-                t0.copy(&self.c);
+                t0 = self.getc();
                 t0.mul(&y.c);
             }
-            t1.copy(&t0);
+            t1 = t0.clone();
             t1.neg();
 
-            self.c.copy(&z2);
+            self.c = z2;
             self.c.add(&t1);
             z3.add(&t1);
             t0.times_i();
             self.b.add(&t0);
             z3.norm();
             z3.times_i();
-            self.a.copy(&z0);
+            self.a = z0;
             self.a.add(&z3);
         } else {
             if self.stype == SPARSER {
@@ -500,11 +470,10 @@ impl FP24 {
             }
             if ecp::SEXTIC_TWIST == SexticTwist::DType {
                 // dense by sparser - 13m
-                let mut z0 = FP8::new_copy(&self.a);
-                let mut z2 = FP8::new_copy(&self.b);
-                let mut z3 = FP8::new_copy(&self.b);
-                let mut t0 = FP8::new_int(0);
-                let mut t1 = FP8::new_copy(&y.a);
+                let mut z0 = self.geta();
+                let mut z2 = self.getb();
+                let mut z3 = self.getb();
+                let mut t1 = y.geta();
 
                 z0.mul(&y.a);
                 z2.pmul(&y.b.geta());
@@ -518,9 +487,9 @@ impl FP24 {
                 z3.norm();
                 z3.pmul(&y.b.geta());
 
-                t0.copy(&z0);
+                let mut t0 = z0.clone();
                 t0.neg();
-                t1.copy(&z2);
+                t1 = z2.clone();
                 t1.neg();
 
                 self.b.add(&t0);
@@ -529,70 +498,65 @@ impl FP24 {
                 z3.add(&t1);
                 z2.add(&t0);
 
-                t0.copy(&self.a);
+                t0 = self.geta();
                 t0.add(&self.c);
                 t0.norm();
                 z3.norm();
                 t0.mul(&y.a);
-                self.c.copy(&z2);
+                self.c = z2;
                 self.c.add(&t0);
 
                 z3.times_i();
-                self.a.copy(&z0);
+                self.a = z0;
                 self.a.add(&z3);
             }
             if ecp::SEXTIC_TWIST == SexticTwist::MType {
-                let mut z0 = FP8::new_copy(&self.a);
-                let mut z1 = FP8::new();
-                let mut z2 = FP8::new();
-                let mut z3 = FP8::new();
-                let mut t0 = FP8::new_copy(&self.a);
-                let mut t1 = FP8::new();
-
+                let mut z0 = self.geta();
+                let mut t0 = self.geta();
                 z0.mul(&y.a);
                 t0.add(&self.b);
                 t0.norm();
 
-                z1.copy(&t0);
+                let mut z1 = t0.clone();
                 z1.mul(&y.a);
-                t0.copy(&self.b);
+                t0 = self.getb();
                 t0.add(&self.c);
                 t0.norm();
 
-                z3.copy(&t0);
+                let mut z3 = t0.clone();
                 z3.pmul(&y.c.getb());
                 z3.times_i();
 
-                t0.copy(&z0);
+                t0 = z0.clone();
                 t0.neg();
                 z1.add(&t0);
-                self.b.copy(&z1);
-                z2.copy(&t0);
+                self.b = z1.clone();
+                let mut z2 = t0.clone();
 
-                t0.copy(&self.a);
+                t0 = self.geta();
                 t0.add(&self.c);
                 t0.norm();
-                t1.copy(&y.a);
+                let mut t1 = y.geta();
                 t1.add(&y.c);
                 t1.norm();
 
                 t0.mul(&t1);
                 z2.add(&t0);
-                t0.copy(&self.c);
+                t0 = self.getc();
 
                 t0.pmul(&y.c.getb());
                 t0.times_i();
-                t1.copy(&t0);
+                t1 = t0.clone();
                 t1.neg();
 
-                self.c.copy(&z2);
+                self.c = z2.clone();
                 self.c.add(&t1);
                 z3.add(&t1);
                 t0.times_i();
                 self.b.add(&t0);
                 z3.norm();
                 z3.times_i();
-                self.a.copy(&z0);
+                self.a = z0.clone();
                 self.a.add(&z3);
             }
         }
@@ -603,49 +567,49 @@ impl FP24 {
     /* Special case of multiplication arises from special form of ATE pairing line function */
     pub fn smul(&mut self, y: &FP24) {
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
-            let mut w1 = FP4::new_copy(&self.a.geta());
-            let mut w2 = FP4::new_copy(&self.a.getb());
-            let mut w3 = FP4::new_copy(&self.b.geta());
+            let mut w1 = self.a.geta();
+            let mut w2 = self.a.getb();
+            let mut w3 = self.b.geta();
 
             w1.mul(&y.a.geta());
             w2.mul(&y.a.getb());
             w3.mul(&y.b.geta());
 
-            let mut ta = FP4::new_copy(&self.a.geta());
-            let mut tb = FP4::new_copy(&y.a.geta());
+            let mut ta = self.a.geta();
+            let mut tb = y.a.geta();
             ta.add(&self.a.getb());
             ta.norm();
             tb.add(&y.a.getb());
             tb.norm();
-            let mut tc = FP4::new_copy(&ta);
+            let mut tc = ta.clone();
             tc.mul(&tb);
-            let mut t = FP4::new_copy(&w1);
+            let mut t = w1.clone();
             t.add(&w2);
             t.neg();
             tc.add(&t);
 
-            ta.copy(&self.a.geta());
+            ta = self.a.geta();
             ta.add(&self.b.geta());
             ta.norm();
-            tb.copy(&y.a.geta());
+            tb = y.a.geta();
             tb.add(&y.b.geta());
             tb.norm();
-            let mut td = FP4::new_copy(&ta);
+            let mut td = ta.clone();
             td.mul(&tb);
-            t.copy(&w1);
+            t = w1.clone();
             t.add(&w3);
             t.neg();
             td.add(&t);
 
-            ta.copy(&self.a.getb());
+            ta = self.a.getb();
             ta.add(&self.b.geta());
             ta.norm();
-            tb.copy(&y.a.getb());
+            tb = y.a.getb();
             tb.add(&y.b.geta());
             tb.norm();
-            let mut te = FP4::new_copy(&ta);
+            let mut te = ta.clone();
             te.mul(&tb);
-            t.copy(&w2);
+            t = w2.clone();
             t.add(&w3);
             t.neg();
             te.add(&t);
@@ -660,49 +624,49 @@ impl FP24 {
             self.a.norm();
             self.b.norm();
         } else {
-            let mut w1 = FP4::new_copy(&self.a.geta());
-            let mut w2 = FP4::new_copy(&self.a.getb());
-            let mut w3 = FP4::new_copy(&self.c.getb());
+            let mut w1 = self.a.geta();
+            let mut w2 = self.a.getb();
+            let mut w3 = self.c.getb();
 
             w1.mul(&y.a.geta());
             w2.mul(&y.a.getb());
             w3.mul(&y.c.getb());
 
-            let mut ta = FP4::new_copy(&self.a.geta());
-            let mut tb = FP4::new_copy(&y.a.geta());
+            let mut ta = self.a.geta();
+            let mut tb = y.a.geta();
             ta.add(&self.a.getb());
             ta.norm();
             tb.add(&y.a.getb());
             tb.norm();
-            let mut tc = FP4::new_copy(&ta);
+            let mut tc = ta.clone();
             tc.mul(&tb);
-            let mut t = FP4::new_copy(&w1);
+            let mut t = w1.clone();
             t.add(&w2);
             t.neg();
             tc.add(&t);
 
-            ta.copy(&self.a.geta());
+            ta = self.a.geta();
             ta.add(&self.c.getb());
             ta.norm();
-            tb.copy(&y.a.geta());
+            tb = y.a.geta();
             tb.add(&y.c.getb());
             tb.norm();
-            let mut td = FP4::new_copy(&ta);
+            let mut td = ta.clone();
             td.mul(&tb);
-            t.copy(&w1);
+            t = w1.clone();
             t.add(&w3);
             t.neg();
             td.add(&t);
 
-            ta.copy(&self.a.getb());
+            ta = self.a.getb();
             ta.add(&self.c.getb());
             ta.norm();
-            tb.copy(&y.a.getb());
+            tb = y.a.getb();
             tb.add(&y.c.getb());
             tb.norm();
-            let mut te = FP4::new_copy(&ta);
+            let mut te = ta.clone();
             te.mul(&tb);
-            t.copy(&w2);
+            t = w2.clone();
             t.add(&w3);
             t.neg();
             te.add(&t);
@@ -727,10 +691,10 @@ impl FP24 {
 
     /* self=1/self */
     pub fn inverse(&mut self) {
-        let mut f0 = FP8::new_copy(&self.a);
-        let mut f1 = FP8::new_copy(&self.b);
-        let mut f2 = FP8::new_copy(&self.a);
-        let mut f3 = FP8::new();
+        let mut f0 = self.geta();
+        let mut f1 = self.getb();
+        let mut f2 = self.geta();
+        let mut f3 = self.geta();
 
         //self.norm();
         f0.sqr();
@@ -739,21 +703,20 @@ impl FP24 {
         f0.sub(&f1);
         f0.norm();
 
-        f1.copy(&self.c);
+        f1 = self.getc();
         f1.sqr();
         f1.times_i();
         f2.mul(&self.b);
         f1.sub(&f2);
         f1.norm();
 
-        f2.copy(&self.b);
+        f2 = self.getb();
         f2.sqr();
-        f3.copy(&self.a);
         f3.mul(&self.c);
         f2.sub(&f3);
         f2.norm();
 
-        f3.copy(&self.b);
+        f3 = self.getb();
         f3.mul(&f2);
         f3.times_i();
         self.a.mul(&f0);
@@ -764,19 +727,19 @@ impl FP24 {
         f3.add(&self.c);
         f3.norm();
         f3.inverse();
-        self.a.copy(&f0);
+        self.a = f0.clone();
         self.a.mul(&f3);
-        self.b.copy(&f1);
+        self.b = f1.clone();
         self.b.mul(&f3);
-        self.c.copy(&f2);
+        self.c = f2.clone();
         self.c.mul(&f3);
         self.stype = DENSE;
     }
 
     /* self=self^p using Frobenius */
     pub fn frob(&mut self, f: &FP2, n: isize) {
-        let mut f2 = FP2::new_copy(f);
-        let mut f3 = FP2::new_copy(f);
+        let mut f2 = f.clone();
+        let mut f3 = f.clone();
 
         f2.sqr();
         f3.mul(&f2);
@@ -800,8 +763,7 @@ impl FP24 {
 
     /* trace function */
     pub fn trace(&mut self) -> FP8 {
-        let mut t = FP8::new();
-        t.copy(&self.a);
+        let mut t = self.geta();
         t.imul(3);
         t.reduce();
         return t;
@@ -815,144 +777,144 @@ impl FP24 {
         for i in 0..mb {
             t[i] = w[i]
         }
-        let mut a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + mb]
         }
-        let mut b = Big::frombytes(&t);
-        let mut c = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 2 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 3 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        let mut d = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        let mut ea = FP4::new_fp2s(&c, &d);
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 4 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 5 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 6 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 7 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        let mut eb = FP4::new_fp2s(&c, &d);
+        let eb = FP4::new_fp2s(c, d);
 
-        let e = FP8::new_fp4s(&ea, &eb);
+        let e = FP8::new_fp4s(ea, eb);
 
         for i in 0..mb {
             t[i] = w[i + 8 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 9 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 10 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 11 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        ea.copy(&FP4::new_fp2s(&c, &d));
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 12 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 13 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 14 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 15 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        eb.copy(&FP4::new_fp2s(&c, &d));
+        let eb = FP4::new_fp2s(c, d);
 
-        let f = FP8::new_fp4s(&ea, &eb);
+        let f = FP8::new_fp4s(ea, eb);
 
         for i in 0..mb {
             t[i] = w[i + 16 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 17 * mb]
         }
-        b.copy(&Big::frombytes(&t));
+        let b = Big::frombytes(&t);
 
-        c.copy(&FP2::new_bigs(&a, &b));
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 18 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 19 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        ea.copy(&FP4::new_fp2s(&c, &d));
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 20 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 21 * mb]
         }
-        b.copy(&Big::frombytes(&t));
+        let b = Big::frombytes(&t);
 
-        c.copy(&FP2::new_bigs(&a, &b));
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 22 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 23 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        eb.copy(&FP4::new_fp2s(&c, &d));
+        let eb = FP4::new_fp2s(c, d);
 
-        let g = FP8::new_fp4s(&ea, &eb);
+        let g = FP8::new_fp4s(ea, eb);
 
-        return FP24::new_fp8s(&e, &f, &g);
+        return FP24::new_fp8s(e, f, g);
     }
 
     /* convert this to byte array */
@@ -1075,14 +1037,14 @@ impl FP24 {
 
     /* self=self^e */
     pub fn pow(&self, e: &Big) -> FP24 {
-        let mut r = FP24::new_copy(self);
+        let mut r = self.clone();
         r.norm();
-        let mut e1 = Big::new_copy(e);
+        let mut e1 = e.clone();
         e1.norm();
-        let mut e3 = Big::new_copy(&e1);
+        let mut e3 = e1.clone();
         e3.pmul(3);
         e3.norm();
-        let mut w = FP24::new_copy(&r);
+        let mut w = r.clone();
 
         let nb = e3.nbits();
         for i in (1..nb - 1).rev() {
@@ -1104,32 +1066,31 @@ impl FP24 {
 
     /* constant time powering by small integer of max length bts */
     pub fn pinpow(&mut self, e: i32, bts: i32) {
-        let mut r: [FP24; 2] = [FP24::new_int(1), FP24::new_copy(self)];
-        let mut t = FP24::new();
+        let mut r: [FP24; 2] = [FP24::new_int(1), self.clone()];
 
         for i in (0..bts).rev() {
             let b: usize = ((e >> i) & 1) as usize;
-            t.copy(&r[b]);
+            let t = r[b].clone();
             r[1 - b].mul(&t);
             r[b].usqr();
         }
-        self.copy(&r[0]);
+        *self = r[0].clone();
     }
 
     pub fn compow(&mut self, e: &Big, r: &Big) -> FP8 {
-        let f = FP2::new_bigs(&Big::new_ints(&rom::FRA), &Big::new_ints(&rom::FRB));
+        let f = FP2::new_bigs(Big::new_ints(&rom::FRA), Big::new_ints(&rom::FRB));
         let q = Big::new_ints(&rom::MODULUS);
 
-        let mut g1 = FP24::new_copy(self);
-        let mut g2 = FP24::new_copy(self);
+        let mut g1 = self.clone();
+        let mut g2 = self.clone();
 
-        let mut m = Big::new_copy(&q);
+        let mut m = q.clone();
         m.rmod(&r);
 
-        let mut a = Big::new_copy(&e);
+        let mut a = e.clone();
         a.rmod(&mut m);
 
-        let mut b = Big::new_copy(&e);
+        let mut b = e.clone();
         b.div(&mut m);
 
         let mut c = g1.trace();
@@ -1178,7 +1139,6 @@ impl FP24 {
             FP24::new(),
         ];
 
-        let mut r = FP24::new();
         let mut p = FP24::new();
         const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize);
         let mut w1: [i8; CT] = [0; CT];
@@ -1188,14 +1148,14 @@ impl FP24 {
 
         let mut mt = Big::new();
         let mut t: [Big; 8] = [
-            Big::new_copy(&u[0]),
-            Big::new_copy(&u[1]),
-            Big::new_copy(&u[2]),
-            Big::new_copy(&u[3]),
-            Big::new_copy(&u[4]),
-            Big::new_copy(&u[5]),
-            Big::new_copy(&u[6]),
-            Big::new_copy(&u[7]),
+            u[0].clone(),
+            u[1].clone(),
+            u[2].clone(),
+            u[3].clone(),
+            u[4].clone(),
+            u[5].clone(),
+            u[6].clone(),
+            u[7].clone(),
         ];
 
         for i in 0..8 {
@@ -1203,32 +1163,32 @@ impl FP24 {
         }
 
         // precomputation
-        g1[0].copy(&q[0]);
-        r.copy(&g1[0]);
-        g1[1].copy(&r);
+        g1[0] = q[0].clone();
+        let mut r = g1[0].clone();
+        g1[1] = r.clone();
         g1[1].mul(&q[1]); // q[0].q[1]
-        g1[2].copy(&r);
+        g1[2] = r.clone();
         g1[2].mul(&q[2]);
-        r.copy(&g1[1]); // q[0].q[2]
-        g1[3].copy(&r);
+        r = g1[1].clone(); // q[0].q[2]
+        g1[3] = r.clone();
         g1[3].mul(&q[2]);
-        r.copy(&g1[0]); // q[0].q[1].q[2]
-        g1[4].copy(&r);
+        r = g1[0].clone(); // q[0].q[1].q[2]
+        g1[4] = r.clone();
         g1[4].mul(&q[3]);
-        r.copy(&g1[1]); // q[0].q[3]
-        g1[5].copy(&r);
+        r = g1[1].clone(); // q[0].q[3]
+        g1[5] = r.clone();
         g1[5].mul(&q[3]);
-        r.copy(&g1[2]); // q[0].q[1].q[3]
-        g1[6].copy(&r);
+        r = g1[2].clone(); // q[0].q[1].q[3]
+        g1[6] = r.clone();
         g1[6].mul(&q[3]);
-        r.copy(&g1[3]); // q[0].q[2].q[3]
-        g1[7].copy(&r);
+        r = g1[3].clone(); // q[0].q[2].q[3]
+        g1[7] = r.clone();
         g1[7].mul(&q[3]); // q[0].q[1].q[2].q[3]
 
         // Use Frobenius
-        let f = FP2::new_bigs(&Big::new_ints(&rom::FRA), &Big::new_ints(&rom::FRB));
+        let f = FP2::new_bigs(Big::new_ints(&rom::FRA), Big::new_ints(&rom::FRB));
         for i in 0..8 {
-            g2[i].copy(&g1[i]);
+            g2[i] = g1[i].clone();
             g2[i].frob(&f, 4);
         }
 
@@ -1298,12 +1258,12 @@ impl FP24 {
         }
 
         // apply correction
-        r.copy(&q[0]);
+        r = q[0].clone();
         r.conj();
         r.mul(&p);
         p.cmove(&r, pb1);
 
-        r.copy(&q[4]);
+        r = q[4].clone();
         r.conj();
         r.mul(&p);
         p.cmove(&r, pb2);
diff --git a/src/fp4.rs b/src/fp4.rs
index 88b5d03..a9d972b 100644
--- a/src/fp4.rs
+++ b/src/fp4.rs
@@ -22,7 +22,7 @@ use super::fp::FP;
 use super::fp2::FP2;
 use std::str::SplitWhitespace;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct FP4 {
     a: FP2,
     b: FP2,
@@ -43,45 +43,32 @@ impl FP4 {
     }
 
     pub fn new_int(a: isize) -> FP4 {
-        let mut f = FP4::new();
-        f.a.copy(&FP2::new_int(a));
-        f.b.zero();
-        return f;
-    }
-
-    pub fn new_copy(x: &FP4) -> FP4 {
-        let mut f = FP4::new();
-        f.a.copy(&x.a);
-        f.b.copy(&x.b);
-        return f;
+        FP4 {
+            a: FP2::new_int(a),
+            b: FP2::new(),
+        }
     }
 
-    pub fn new_fp2s(c: &FP2, d: &FP2) -> FP4 {
-        let mut f = FP4::new();
-        f.a.copy(c);
-        f.b.copy(d);
-        return f;
+    pub fn new_fp2s(a: FP2, b: FP2) -> FP4 {
+        FP4 { a, b }
     }
 
-    pub fn new_fp2(c: &FP2) -> FP4 {
-        let mut f = FP4::new();
-        f.a.copy(c);
-        f.b.zero();
-        return f;
+    pub fn new_fp2(a: FP2) -> FP4 {
+        FP4 { a, b: FP2::new() }
     }
 
     pub fn set_fp2s(&mut self, c: &FP2, d: &FP2) {
-        self.a.copy(&c);
-        self.b.copy(&d);
+        self.a = c.clone();
+        self.b = d.clone();
     }
 
     pub fn set_fp2(&mut self, c: &FP2) {
-        self.a.copy(&c);
+        self.a = c.clone();
         self.b.zero();
     }
 
     pub fn set_fp2h(&mut self, c: &FP2) {
-        self.b.copy(&c);
+        self.b = c.clone();
         self.a.zero();
     }
 
@@ -104,46 +91,38 @@ impl FP4 {
 
     /* test self=0 ? */
     pub fn iszilch(&self) -> bool {
-        return self.a.iszilch() && self.b.iszilch();
+        self.a.iszilch() && self.b.iszilch()
     }
 
     /* test self=1 ? */
     pub fn isunity(&self) -> bool {
         let one = FP2::new_int(1);
-        return self.a.equals(&one) && self.b.iszilch();
+        self.a.equals(&one) && self.b.iszilch()
     }
 
     /* test is w real? That is in a+ib test b is zero */
     pub fn isreal(&self) -> bool {
-        return self.b.iszilch();
+        self.b.iszilch()
     }
+
     /* extract real part a */
     pub fn real(&self) -> FP2 {
-        let f = FP2::new_copy(&self.a);
-        return f;
+        self.geta()
     }
 
     pub fn geta(&self) -> FP2 {
-        return self.a;
-        //        let f = FP2::new_copy(&self.a);
-        //        return f;
+        self.a.clone()
     }
+
     /* extract imaginary part b */
     pub fn getb(&self) -> FP2 {
-        return self.b;
-        //        let f = FP2::new_copy(&self.b);
-        //        return f;
+        self.b.clone()
     }
 
     /* test self=x */
     pub fn equals(&self, x: &FP4) -> bool {
         return self.a.equals(&x.a) && self.b.equals(&x.b);
     }
-    /* copy self=x */
-    pub fn copy(&mut self, x: &FP4) {
-        self.a.copy(&x.a);
-        self.b.copy(&x.b);
-    }
 
     /* set self=0 */
     pub fn zero(&mut self) {
@@ -160,16 +139,15 @@ impl FP4 {
     /* negate self mod Modulus */
     pub fn neg(&mut self) {
         self.norm();
-        let mut m = FP2::new_copy(&self.a);
-        let mut t = FP2::new();
+        let mut m = self.geta();
 
         m.add(&self.b);
         m.neg();
-        t.copy(&m);
+        let mut t = m.clone();
         t.add(&self.b);
-        self.b.copy(&m);
+        self.b = m.clone();
         self.b.add(&self.a);
-        self.a.copy(&t);
+        self.a = t.clone();
         self.norm();
     }
 
@@ -202,7 +180,7 @@ impl FP4 {
 
     /* self-=a */
     pub fn sub(&mut self, x: &FP4) {
-        let mut m = FP4::new_copy(x);
+        let mut m = x.clone();
         m.neg();
         self.add(&m);
     }
@@ -234,9 +212,9 @@ impl FP4 {
     /* self*=self */
 
     pub fn sqr(&mut self) {
-        let mut t1 = FP2::new_copy(&self.a);
-        let mut t2 = FP2::new_copy(&self.b);
-        let mut t3 = FP2::new_copy(&self.a);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
+        let mut t3 = self.geta();
 
         t3.mul(&self.b);
         t1.add(&self.b);
@@ -247,11 +225,11 @@ impl FP4 {
         t1.norm();
         t2.norm();
 
-        self.a.copy(&t1);
+        self.a = t1.clone();
 
         self.a.mul(&t2);
 
-        t2.copy(&t3);
+        t2 = t3.clone();
         t2.mul_ip();
         t2.add(&t3);
         t2.norm();
@@ -259,7 +237,7 @@ impl FP4 {
         self.a.add(&t2);
 
         t3.dbl();
-        self.b.copy(&t3);
+        self.b = t3.clone();
 
         self.norm();
     }
@@ -268,14 +246,13 @@ impl FP4 {
     pub fn mul(&mut self, y: &FP4) {
         //self.norm();
 
-        let mut t1 = FP2::new_copy(&self.a);
-        let mut t2 = FP2::new_copy(&self.b);
-        let mut t3 = FP2::new();
-        let mut t4 = FP2::new_copy(&self.b);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
+        let mut t3 = y.getb();
+        let mut t4 = self.getb();
 
         t1.mul(&y.a);
         t2.mul(&y.b);
-        t3.copy(&y.b);
         t3.add(&y.a);
         t4.add(&self.a);
 
@@ -284,18 +261,18 @@ impl FP4 {
 
         t4.mul(&t3);
 
-        t3.copy(&t1);
+        t3 = t1.clone();
         t3.neg();
         t4.add(&t3);
         t4.norm();
 
-        t3.copy(&t2);
+        t3 = t2.clone();
         t3.neg();
-        self.b.copy(&t4);
+        self.b = t4.clone();
         self.b.add(&t3);
 
         t2.mul_ip();
-        self.a.copy(&t2);
+        self.a = t2.clone();
         self.a.add(&t1);
 
         self.norm();
@@ -326,8 +303,8 @@ impl FP4 {
     pub fn inverse(&mut self) {
         //self.norm();
 
-        let mut t1 = FP2::new_copy(&self.a);
-        let mut t2 = FP2::new_copy(&self.b);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
 
         t1.sqr();
         t2.sqr();
@@ -343,12 +320,12 @@ impl FP4 {
 
     /* self*=i where i = sqrt(-1+sqrt(-1)) */
     pub fn times_i(&mut self) {
-        let mut s = FP2::new_copy(&self.b);
-        let mut t = FP2::new_copy(&self.b);
+        let mut s = self.getb();
+        let mut t = self.getb();
         s.times_i();
         t.add(&s);
-        self.b.copy(&self.a);
-        self.a.copy(&t);
+        self.b = self.geta();
+        self.a = t.clone();
         self.norm();
     }
 
@@ -361,9 +338,9 @@ impl FP4 {
 
     /* self=self^e */
     pub fn pow(&self, e: &Big) -> FP4 {
-        let mut w = FP4::new_copy(self);
+        let mut w = self.clone();
         w.norm();
-        let mut z = Big::new_copy(&e);
+        let mut z = e.clone();
         let mut r = FP4::new_int(1);
         z.norm();
         loop {
@@ -383,8 +360,8 @@ impl FP4 {
 
     /* XTR xtr_a function */
     pub fn xtr_a(&mut self, w: &FP4, y: &FP4, z: &FP4) {
-        let mut r = FP4::new_copy(w);
-        let mut t = FP4::new_copy(w);
+        let mut r = w.clone();
+        let mut t = w.clone();
         r.sub(y);
         r.norm();
         r.pmul(&self.a);
@@ -393,7 +370,7 @@ impl FP4 {
         t.pmul(&self.b);
         t.times_i();
 
-        self.copy(&r);
+        *self = r.clone();
         self.add(&t);
         self.add(z);
 
@@ -402,7 +379,7 @@ impl FP4 {
 
     /* XTR xtr_d function */
     pub fn xtr_d(&mut self) {
-        let mut w = FP4::new_copy(self);
+        let mut w = self.clone();
         self.sqr();
         w.conj();
         w.dbl();
@@ -413,17 +390,15 @@ impl FP4 {
 
     /* r=x^n using XTR method on traces of FP12s */
     pub fn xtr_pow(&self, n: &Big) -> FP4 {
-        let mut sf = FP4::new_copy(self);
+        let mut sf = self.clone();
         sf.norm();
         let mut a = FP4::new_int(3);
-        let mut b = FP4::new_copy(&sf);
-        let mut c = FP4::new_copy(&b);
+        let mut b = sf.clone();
+        let mut c = b.clone();
         c.xtr_d();
-        let mut t = FP4::new();
-        let mut r = FP4::new();
 
         let par = n.parity();
-        let mut v = Big::new_copy(n);
+        let mut v = n.clone();
         v.norm();
         v.fshr(1);
         if par == 0 {
@@ -434,46 +409,39 @@ impl FP4 {
         let nb = v.nbits();
         for i in (0..nb).rev() {
             if v.bit(i) != 1 {
-                t.copy(&b);
+                let t = b.clone();
                 sf.conj();
                 c.conj();
                 b.xtr_a(&a, &sf, &c);
                 sf.conj();
-                c.copy(&t);
+                c = t.clone();
                 c.xtr_d();
                 a.xtr_d();
             } else {
-                t.copy(&a);
+                let mut t = a.clone();
                 t.conj();
-                a.copy(&b);
+                a = b.clone();
                 a.xtr_d();
                 b.xtr_a(&c, &sf, &t);
                 c.xtr_d();
             }
         }
-        if par == 0 {
-            r.copy(&c)
-        } else {
-            r.copy(&b)
-        }
+        let mut r = if par == 0 { c.clone() } else { b.clone() };
         r.reduce();
-        return r;
+        r
     }
 
     /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
     pub fn xtr_pow2(&mut self, ck: &FP4, ckml: &FP4, ckm2l: &FP4, a: &Big, b: &Big) -> FP4 {
-        let mut e = Big::new_copy(a);
-        let mut d = Big::new_copy(b);
-        let mut w = Big::new();
+        let mut e = a.clone();
+        let mut d = b.clone();
         e.norm();
         d.norm();
 
-        let mut cu = FP4::new_copy(ck); // can probably be passed in w/o copying
-        let mut cv = FP4::new_copy(self);
-        let mut cumv = FP4::new_copy(ckml);
-        let mut cum2v = FP4::new_copy(ckm2l);
-        let mut r = FP4::new();
-        let mut t = FP4::new();
+        let mut cu = ck.clone(); // can probably be passed in w/o copying
+        let mut cv = self.clone();
+        let mut cumv = ckml.clone();
+        let mut cum2v = ckm2l.clone();
 
         let mut f2: usize = 0;
         while d.parity() == 0 && e.parity() == 0 {
@@ -484,125 +452,125 @@ impl FP4 {
 
         while Big::comp(&d, &e) != 0 {
             if Big::comp(&d, &e) > 0 {
-                w.copy(&e);
+                let mut w = e.clone();
                 w.imul(4);
                 w.norm();
                 if Big::comp(&d, &w) <= 0 {
-                    w.copy(&d);
-                    d.copy(&e);
+                    w = d.clone();
+                    d = e.clone();
                     e.rsub(&w);
                     e.norm();
 
-                    t.copy(&cv);
+                    let mut t = cv.clone();
                     t.xtr_a(&cu, &cumv, &cum2v);
-                    cum2v.copy(&cumv);
+                    cum2v = cumv.clone();
                     cum2v.conj();
-                    cumv.copy(&cv);
-                    cv.copy(&cu);
-                    cu.copy(&t);
+                    cumv = cv.clone();
+                    cv = cu.clone();
+                    cu = t.clone();
                 } else {
                     if d.parity() == 0 {
                         d.fshr(1);
-                        r.copy(&cum2v);
+                        let mut r = cum2v.clone();
                         r.conj();
-                        t.copy(&cumv);
+                        let mut t = cumv.clone();
                         t.xtr_a(&cu, &cv, &r);
-                        cum2v.copy(&cumv);
+                        cum2v = cumv.clone();
                         cum2v.xtr_d();
-                        cumv.copy(&t);
+                        cumv = t.clone();
                         cu.xtr_d();
                     } else {
                         if e.parity() == 1 {
                             d.sub(&e);
                             d.norm();
                             d.fshr(1);
-                            t.copy(&cv);
+                            let mut t = cv.clone();
                             t.xtr_a(&cu, &cumv, &cum2v);
                             cu.xtr_d();
-                            cum2v.copy(&cv);
+                            cum2v = cv.clone();
                             cum2v.xtr_d();
                             cum2v.conj();
-                            cv.copy(&t);
+                            cv = t.clone();
                         } else {
-                            w.copy(&d);
-                            d.copy(&e);
+                            w = d.clone();
+                            d = e.clone();
                             d.fshr(1);
-                            e.copy(&w);
-                            t.copy(&cumv);
+                            e = w.clone();
+                            let mut t = cumv.clone();
                             t.xtr_d();
-                            cumv.copy(&cum2v);
+                            cumv = cum2v.clone();
                             cumv.conj();
-                            cum2v.copy(&t);
+                            cum2v = t.clone();
                             cum2v.conj();
-                            t.copy(&cv);
+                            t = cv.clone();
                             t.xtr_d();
-                            cv.copy(&cu);
-                            cu.copy(&t);
+                            cv = cu.clone();
+                            cu = t.clone();
                         }
                     }
                 }
             }
             if Big::comp(&d, &e) < 0 {
-                w.copy(&d);
+                let mut w = d.clone();
                 w.imul(4);
                 w.norm();
                 if Big::comp(&e, &w) <= 0 {
                     e.sub(&d);
                     e.norm();
-                    t.copy(&cv);
+                    let mut t = cv.clone();
                     t.xtr_a(&cu, &cumv, &cum2v);
-                    cum2v.copy(&cumv);
-                    cumv.copy(&cu);
-                    cu.copy(&t);
+                    cum2v = cumv.clone();
+                    cumv = cu.clone();
+                    cu = t.clone()
                 } else {
                     if e.parity() == 0 {
-                        w.copy(&d);
-                        d.copy(&e);
+                        w = d.clone();
+                        d = e.clone();
                         d.fshr(1);
-                        e.copy(&w);
-                        t.copy(&cumv);
+                        e = w.clone();
+                        let mut t = cumv.clone();
                         t.xtr_d();
-                        cumv.copy(&cum2v);
+                        cumv = cum2v.clone();
                         cumv.conj();
-                        cum2v.copy(&t);
+                        cum2v = t.clone();
                         cum2v.conj();
-                        t.copy(&cv);
+                        t = cv.clone();
                         t.xtr_d();
-                        cv.copy(&cu);
-                        cu.copy(&t);
+                        cv = cu.clone();
+                        cu = t.clone();
                     } else {
                         if d.parity() == 1 {
-                            w.copy(&e);
-                            e.copy(&d);
+                            w = e.clone();
+                            e = d.clone();
                             w.sub(&d);
                             w.norm();
-                            d.copy(&w);
+                            d = w.clone();
                             d.fshr(1);
-                            t.copy(&cv);
+                            let mut t = cv.clone();
                             t.xtr_a(&cu, &cumv, &cum2v);
                             cumv.conj();
-                            cum2v.copy(&cu);
+                            cum2v = cu.clone();
                             cum2v.xtr_d();
                             cum2v.conj();
-                            cu.copy(&cv);
+                            cu = cv.clone();
                             cu.xtr_d();
-                            cv.copy(&t);
+                            cv = t.clone();
                         } else {
                             d.fshr(1);
-                            r.copy(&cum2v);
+                            let mut r = cum2v.clone();
                             r.conj();
-                            t.copy(&cumv);
+                            let mut t = cumv.clone();
                             t.xtr_a(&cu, &cv, &r);
-                            cum2v.copy(&cumv);
+                            cum2v = cumv.clone();
                             cum2v.xtr_d();
-                            cumv.copy(&t);
+                            cumv = t.clone();
                             cu.xtr_d();
                         }
                     }
                 }
             }
         }
-        r.copy(&cv);
+        let mut r = cv.clone();
         r.xtr_a(&cu, &cumv, &cum2v);
         for _ in 0..f2 {
             r.xtr_d()
@@ -618,21 +586,21 @@ impl FP4 {
     }
 
     pub fn div_i(&mut self) {
-        let mut u = FP2::new_copy(&self.a);
-        let v = FP2::new_copy(&self.b);
+        let mut u = self.geta();
+        let v = self.getb();
         u.div_ip();
-        self.a.copy(&v);
-        self.b.copy(&u);
+        self.a = v;
+        self.b = u;
     }
 
     pub fn div_2i(&mut self) {
-        let mut u = FP2::new_copy(&self.a);
-        let mut v = FP2::new_copy(&self.b);
+        let mut u = self.geta();
+        let mut v = self.getb();
         u.div_ip2();
         v.dbl();
         v.norm();
-        self.a.copy(&v);
-        self.b.copy(&u);
+        self.a = v.clone();
+        self.b = u.clone();
     }
 
     /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
@@ -642,18 +610,18 @@ impl FP4 {
             return true;
         }
 
-        let mut a = FP2::new_copy(&self.a);
-        let mut s = FP2::new_copy(&self.b);
-        let mut t = FP2::new_copy(&self.a);
+        let mut a = self.geta();
+        let mut s = self.getb();
+        let mut t = self.geta();
 
         if s.iszilch() {
             if t.sqrt() {
-                self.a.copy(&t);
+                self.a = t.clone();
                 self.b.zero();
             } else {
                 t.div_ip();
                 t.sqrt();
-                self.b.copy(&t);
+                self.b = t.clone();
                 self.a.zero();
             }
             return true;
@@ -664,18 +632,18 @@ impl FP4 {
         s.norm();
         a.sub(&s);
 
-        s.copy(&a);
+        s = a.clone();
         if !s.sqrt() {
             return false;
         }
 
-        a.copy(&t);
+        a = t.clone();
         a.add(&s);
         a.norm();
         a.div2();
 
         if !a.sqrt() {
-            a.copy(&t);
+            a = t.clone();
             a.sub(&s);
             a.norm();
             a.div2();
@@ -683,14 +651,14 @@ impl FP4 {
                 return false;
             }
         }
-        t.copy(&self.b);
-        s.copy(&a);
+        t = self.getb();
+        s = a.clone();
         s.add(&a);
         s.inverse();
 
         t.mul(&s);
-        self.a.copy(&a);
-        self.b.copy(&t);
+        self.a = a;
+        self.b = t;
 
         return true;
     }
diff --git a/src/fp48.rs b/src/fp48.rs
index ad1cf53..fd8b412 100644
--- a/src/fp48.rs
+++ b/src/fp48.rs
@@ -34,7 +34,7 @@ pub const SPARSER: usize = 2;
 pub const SPARSE: usize = 3;
 pub const DENSE: usize = 4;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct FP48 {
     a: FP16,
     b: FP16,
@@ -62,7 +62,7 @@ impl FP48 {
 
     pub fn new_int(a: isize) -> FP48 {
         let mut f = FP48::new();
-        f.a.copy(&FP16::new_int(a));
+        f.a = FP16::new_int(a);
         f.b.zero();
         f.c.zero();
         if a == 1 {
@@ -73,31 +73,22 @@ impl FP48 {
         return f;
     }
 
-    pub fn new_copy(x: &FP48) -> FP48 {
-        let mut f = FP48::new();
-        f.a.copy(&x.a);
-        f.b.copy(&x.b);
-        f.c.copy(&x.c);
-        f.stype = x.stype;
-        return f;
-    }
-
-    pub fn new_fp16s(d: &FP16, e: &FP16, f: &FP16) -> FP48 {
-        let mut g = FP48::new();
-        g.a.copy(d);
-        g.b.copy(e);
-        g.c.copy(f);
-        g.stype = DENSE;
-        return g;
+    pub fn new_fp16s(a: FP16, b: FP16, c: FP16) -> FP48 {
+        FP48 {
+            a,
+            b,
+            c,
+            stype: DENSE,
+        }
     }
 
-    pub fn new_fp16(d: &FP16) -> FP48 {
-        let mut g = FP48::new();
-        g.a.copy(d);
-        g.b.zero();
-        g.c.zero();
-        g.stype = SPARSER;
-        return g;
+    pub fn new_fp16(a: FP16) -> FP48 {
+        FP48 {
+            a,
+            b: FP16::new(),
+            c: FP16::new(),
+            stype: SPARSER,
+        }
     }
 
     /* reduce components mod Modulus */
@@ -152,7 +143,7 @@ impl FP48 {
         self.cmove(&g[6], FP48::teq(babs, 6));
         self.cmove(&g[7], FP48::teq(babs, 7));
 
-        let mut invf = FP48::new_copy(self);
+        let mut invf = self.clone();
         invf.conj();
         self.cmove(&invf, (m & 1) as isize);
     }
@@ -169,23 +160,15 @@ impl FP48 {
     }
 
     pub fn geta(&self) -> FP16 {
-        return self.a;
+        self.a.clone()
     }
 
     pub fn getb(&self) -> FP16 {
-        return self.b;
+        self.b.clone()
     }
 
     pub fn getc(&self) -> FP16 {
-        return self.c;
-    }
-
-    /* copy self=x */
-    pub fn copy(&mut self, x: &FP48) {
-        self.a.copy(&x.a);
-        self.b.copy(&x.b);
-        self.c.copy(&x.c);
-        self.stype = x.stype;
+        self.c.clone()
     }
 
     /* set self=1 */
@@ -213,13 +196,12 @@ impl FP48 {
 
     /* Granger-Scott Unitary Squaring */
     pub fn usqr(&mut self) {
-        let mut a = FP16::new_copy(&self.a);
-        let mut b = FP16::new_copy(&self.c);
-        let mut c = FP16::new_copy(&self.b);
-        let mut d = FP16::new();
+        let mut a = self.geta();
+        let mut b = self.getc();
+        let mut c = self.getb();
 
         self.a.sqr();
-        d.copy(&self.a);
+        let mut d = self.geta();
         d.add(&self.a);
         self.a.add(&d);
 
@@ -231,13 +213,13 @@ impl FP48 {
         b.sqr();
         b.times_i();
 
-        d.copy(&b);
+        d = b.clone();
         d.add(&b);
         b.add(&d);
         b.norm();
 
         c.sqr();
-        d.copy(&c);
+        d = c.clone();
         d.add(&c);
         c.add(&d);
         c.norm();
@@ -258,10 +240,10 @@ impl FP48 {
         if self.stype == ONE {
             return;
         }
-        let mut a = FP16::new_copy(&self.a);
-        let mut b = FP16::new_copy(&self.b);
-        let mut c = FP16::new_copy(&self.c);
-        let mut d = FP16::new_copy(&self.a);
+        let mut a = self.geta();
+        let mut b = self.getb();
+        let mut c = self.getc();
+        let mut d = self.geta();
 
         a.sqr();
         b.mul(&self.c);
@@ -276,7 +258,7 @@ impl FP48 {
         self.c.norm();
         self.c.sqr();
 
-        self.a.copy(&a);
+        self.a = a.clone();
         a.add(&b);
         a.norm();
         a.add(&c);
@@ -289,7 +271,7 @@ impl FP48 {
 
         self.a.add(&b);
 
-        self.b.copy(&c);
+        self.b = c;
         self.b.add(&d);
         self.c.add(&a);
         if self.stype == SPARSER {
@@ -302,12 +284,10 @@ impl FP48 {
 
     /* FP48 full multiplication self=self*y */
     pub fn mul(&mut self, y: &FP48) {
-        let mut z0 = FP16::new_copy(&self.a);
-        let mut z1 = FP16::new();
-        let mut z2 = FP16::new_copy(&mut self.b);
-        let mut z3 = FP16::new();
-        let mut t0 = FP16::new_copy(&self.a);
-        let mut t1 = FP16::new_copy(&y.a);
+        let mut z0 = self.geta();
+        let mut z2 = self.getb();
+        let mut t0 = self.geta();
+        let mut t1 = y.geta();
 
         z0.mul(&y.a);
         z2.mul(&y.b);
@@ -318,46 +298,46 @@ impl FP48 {
         t0.norm();
         t1.norm();
 
-        z1.copy(&t0);
+        let mut z1 = t0.clone();
         z1.mul(&t1);
-        t0.copy(&self.b);
+        t0 = self.getb();
         t0.add(&self.c);
-        t1.copy(&y.b);
+        t1 = y.getb();
         t1.add(&y.c);
 
         t0.norm();
         t1.norm();
 
-        z3.copy(&t0);
+        let mut z3 = t0.clone();
         z3.mul(&t1);
 
-        t0.copy(&z0);
+        t0 = z0.clone();
         t0.neg();
-        t1.copy(&z2);
+        t1 = z2.clone();
         t1.neg();
 
         z1.add(&t0);
-        self.b.copy(&z1);
+        self.b = z1.clone();
         self.b.add(&t1);
 
         z3.add(&t1);
         z2.add(&t0);
 
-        t0.copy(&self.a);
+        t0 = self.geta();
         t0.add(&self.c);
         t0.norm();
-        t1.copy(&y.a);
+        t1 = y.geta();
         t1.add(&y.c);
         t1.norm();
         t0.mul(&t1);
         z2.add(&t0);
 
-        t0.copy(&self.c);
+        t0 = self.getc();
         t0.mul(&y.c);
-        t1.copy(&t0);
+        t1 = t0.clone();
         t1.neg();
 
-        self.c.copy(&z2);
+        self.c = z2;
         self.c.add(&t1);
         z3.add(&t1);
         t0.times_i();
@@ -365,91 +345,86 @@ impl FP48 {
         z3.norm();
 
         z3.times_i();
-        self.a.copy(&z0);
+        self.a = z0;
         self.a.add(&z3);
         self.stype = DENSE;
         self.norm();
     }
 
-    /* FP48 full multiplication w=w*y */
-    /* Supports sparse multiplicands */
-    /* Usually w is denser than y */
+    /// FP48 full multiplication w=w*y
+    /// Supports sparse multiplicands
+    /// Usually w is denser than y
     pub fn ssmul(&mut self, y: &FP48) {
         if self.stype == ONE {
-            self.copy(&y);
+            *self = y.clone();
             return;
         }
         if y.stype == ONE {
             return;
         }
         if y.stype >= SPARSE {
-            let mut z0 = FP16::new_copy(&self.a);
-            let mut z1 = FP16::new_int(0);
+            let mut z0 = self.geta();
             let mut z2 = FP16::new_int(0);
-            let mut z3 = FP16::new_int(0);
             z0.mul(&y.a);
 
             if ecp::SEXTIC_TWIST == SexticTwist::MType {
                 if y.stype == SPARSE || self.stype == SPARSE {
-                    let mut ga = FP8::new_int(0);
-                    let mut gb = FP8::new_int(0);
-
-                    gb.copy(&self.b.getb());
+                    let mut gb = self.b.getb();
                     gb.mul(&y.b.getb());
-                    ga.zero();
+                    let mut ga = FP8::new_int(0);
                     if y.stype != SPARSE {
-                        ga.copy(&self.b.getb());
+                        ga = self.b.getb();
                         ga.mul(&y.b.geta());
                     }
                     if self.stype != SPARSE {
-                        ga.copy(&self.b.geta());
+                        ga = self.b.geta();
                         ga.mul(&y.b.getb());
                     }
                     z2.set_fp8s(&ga, &gb);
                     z2.times_i();
                 } else {
-                    z2.copy(&self.b);
+                    z2 = self.getb();
                     z2.mul(&y.b);
                 }
             } else {
-                z2.copy(&self.b);
+                z2 = self.getb();
                 z2.mul(&y.b);
             }
-            let mut t0 = FP16::new_copy(&self.a);
-            let mut t1 = FP16::new_copy(&y.a);
+            let mut t0 = self.geta();
+            let mut t1 = y.geta();
             t0.add(&self.b);
             t0.norm();
             t1.add(&y.b);
             t1.norm();
 
-            z1.copy(&t0);
+            let mut z1 = t0.clone();
             z1.mul(&t1);
-            t0.copy(&self.b);
+            t0 = self.getb();
             t0.add(&self.c);
             t0.norm();
-            t1.copy(&y.b);
+            t1 = y.getb();
             t1.add(&y.c);
             t1.norm();
 
-            z3.copy(&t0);
+            let mut z3 = t0.clone();
             z3.mul(&t1);
 
-            t0.copy(&z0);
+            t0 = z0.clone();
             t0.neg();
-            t1.copy(&z2);
+            t1 = z2.clone();
             t1.neg();
 
             z1.add(&t0);
-            self.b.copy(&z1);
+            self.b = z1.clone();
             self.b.add(&t1);
 
             z3.add(&t1);
             z2.add(&t0);
 
-            t0.copy(&self.a);
+            t0 = self.geta();
             t0.add(&self.c);
             t0.norm();
-            t1.copy(&y.a);
+            t1 = y.geta();
             t1.add(&y.c);
             t1.norm();
 
@@ -458,40 +433,37 @@ impl FP48 {
 
             if ecp::SEXTIC_TWIST == SexticTwist::DType {
                 if y.stype == SPARSE || self.stype == SPARSE {
-                    let mut ga = FP8::new_int(0);
-                    let mut gb = FP8::new_int(0);
-
-                    ga.copy(&self.c.geta());
+                    let mut ga = self.c.geta();
                     ga.mul(&y.c.geta());
-                    gb.zero();
+                    let mut gb = FP8::new_int(0);
                     if y.stype != SPARSE {
-                        gb.copy(&self.c.geta());
+                        gb = self.c.geta();
                         gb.mul(&y.c.getb());
                     }
                     if self.stype != SPARSE {
-                        gb.copy(&self.c.getb());
+                        gb = self.c.getb();
                         gb.mul(&y.c.geta());
                     }
                     t0.set_fp8s(&ga, &gb);
                 } else {
-                    t0.copy(&self.c);
+                    t0 = self.getc();
                     t0.mul(&y.c);
                 }
             } else {
-                t0.copy(&self.c);
+                t0 = self.getc();
                 t0.mul(&y.c);
             }
-            t1.copy(&t0);
+            t1 = t0.clone();
             t1.neg();
 
-            self.c.copy(&z2);
+            self.c = z2.clone();
             self.c.add(&t1);
             z3.add(&t1);
             t0.times_i();
             self.b.add(&t0);
             z3.norm();
             z3.times_i();
-            self.a.copy(&z0);
+            self.a = z0.clone();
             self.a.add(&z3);
         } else {
             if self.stype == SPARSER {
@@ -500,11 +472,10 @@ impl FP48 {
             }
             if ecp::SEXTIC_TWIST == SexticTwist::DType {
                 // dense by sparser - 13m
-                let mut z0 = FP16::new_copy(&self.a);
-                let mut z2 = FP16::new_copy(&self.b);
-                let mut z3 = FP16::new_copy(&self.b);
-                let mut t0 = FP16::new_int(0);
-                let mut t1 = FP16::new_copy(&y.a);
+                let mut z0 = self.geta();
+                let mut z2 = self.getb();
+                let mut z3 = self.getb();
+                let mut t1 = y.geta();
 
                 z0.mul(&y.a);
                 z2.pmul(&y.b.geta());
@@ -518,9 +489,9 @@ impl FP48 {
                 z3.norm();
                 z3.pmul(&y.b.geta());
 
-                t0.copy(&z0);
+                let mut t0 = z0.clone();
                 t0.neg();
-                t1.copy(&z2);
+                t1 = z2.clone();
                 t1.neg();
 
                 self.b.add(&t0);
@@ -529,70 +500,65 @@ impl FP48 {
                 z3.add(&t1);
                 z2.add(&t0);
 
-                t0.copy(&self.a);
+                t0 = self.geta();
                 t0.add(&self.c);
                 t0.norm();
                 z3.norm();
                 t0.mul(&y.a);
-                self.c.copy(&z2);
+                self.c = z2.clone();
                 self.c.add(&t0);
 
                 z3.times_i();
-                self.a.copy(&z0);
+                self.a = z0.clone();
                 self.a.add(&z3);
             }
             if ecp::SEXTIC_TWIST == SexticTwist::MType {
-                let mut z0 = FP16::new_copy(&self.a);
-                let mut z1 = FP16::new();
-                let mut z2 = FP16::new();
-                let mut z3 = FP16::new();
-                let mut t0 = FP16::new_copy(&self.a);
-                let mut t1 = FP16::new();
-
+                let mut t0 = self.geta();
+                let mut z0 = self.geta();
                 z0.mul(&y.a);
                 t0.add(&self.b);
                 t0.norm();
 
-                z1.copy(&t0);
+                let mut z1 = t0.clone();
                 z1.mul(&y.a);
-                t0.copy(&self.b);
+                t0 = self.getb();
                 t0.add(&self.c);
                 t0.norm();
 
-                z3.copy(&t0);
+                let mut z3 = t0.clone();
                 z3.pmul(&y.c.getb());
                 z3.times_i();
 
-                t0.copy(&z0);
+                t0 = z0.clone();
                 t0.neg();
                 z1.add(&t0);
-                self.b.copy(&z1);
-                z2.copy(&t0);
+                self.b = z1.clone();
+                let mut z2 = t0.clone();
 
-                t0.copy(&self.a);
+                t0 = self.geta();
                 t0.add(&self.c);
                 t0.norm();
-                t1.copy(&y.a);
+                let mut t1 = y.geta();
                 t1.add(&y.c);
                 t1.norm();
 
                 t0.mul(&t1);
                 z2.add(&t0);
-                t0.copy(&self.c);
+                t0 = self.getc();
 
                 t0.pmul(&y.c.getb());
                 t0.times_i();
-                t1.copy(&t0);
+                t1 = t0.clone();
                 t1.neg();
 
-                self.c.copy(&z2);
+                self.c = z2;
                 self.c.add(&t1);
                 z3.add(&t1);
                 t0.times_i();
                 self.b.add(&t0);
                 z3.norm();
                 z3.times_i();
-                self.a.copy(&z0);
+                self.a = z0;
                 self.a.add(&z3);
             }
         }
@@ -603,49 +569,49 @@ impl FP48 {
     /* Special case of multiplication arises from special form of ATE pairing line function */
     pub fn smul(&mut self, y: &FP48) {
         if ecp::SEXTIC_TWIST == SexticTwist::DType {
-            let mut w1 = FP8::new_copy(&self.a.geta());
-            let mut w2 = FP8::new_copy(&self.a.getb());
-            let mut w3 = FP8::new_copy(&self.b.geta());
+            let mut w1 = self.a.geta();
+            let mut w2 = self.a.getb();
+            let mut w3 = self.b.geta();
 
             w1.mul(&y.a.geta());
             w2.mul(&y.a.getb());
             w3.mul(&y.b.geta());
 
-            let mut ta = FP8::new_copy(&self.a.geta());
-            let mut tb = FP8::new_copy(&y.a.geta());
+            let mut ta = self.a.geta();
+            let mut tb = y.a.geta();
             ta.add(&self.a.getb());
             ta.norm();
             tb.add(&y.a.getb());
             tb.norm();
-            let mut tc = FP8::new_copy(&ta);
+            let mut tc = ta.clone();
             tc.mul(&tb);
-            let mut t = FP8::new_copy(&w1);
+            let mut t = w1.clone();
             t.add(&w2);
             t.neg();
             tc.add(&t);
 
-            ta.copy(&self.a.geta());
+            ta = self.a.geta();
             ta.add(&self.b.geta());
             ta.norm();
-            tb.copy(&y.a.geta());
+            tb = y.a.geta();
             tb.add(&y.b.geta());
             tb.norm();
-            let mut td = FP8::new_copy(&ta);
+            let mut td = ta.clone();
             td.mul(&tb);
-            t.copy(&w1);
+            t = w1.clone();
             t.add(&w3);
             t.neg();
             td.add(&t);
 
-            ta.copy(&self.a.getb());
+            ta = self.a.getb();
             ta.add(&self.b.geta());
             ta.norm();
-            tb.copy(&y.a.getb());
+            tb = y.a.getb();
             tb.add(&y.b.geta());
             tb.norm();
-            let mut te = FP8::new_copy(&ta);
+            let mut te = ta.clone();
             te.mul(&tb);
-            t.copy(&w2);
+            t = w2.clone();
             t.add(&w3);
             t.neg();
             te.add(&t);
@@ -660,49 +626,49 @@ impl FP48 {
             self.a.norm();
             self.b.norm();
         } else {
-            let mut w1 = FP8::new_copy(&self.a.geta());
-            let mut w2 = FP8::new_copy(&self.a.getb());
-            let mut w3 = FP8::new_copy(&self.c.getb());
+            let mut w1 = self.a.geta();
+            let mut w2 = self.a.getb();
+            let mut w3 = self.c.getb();
 
             w1.mul(&y.a.geta());
             w2.mul(&y.a.getb());
             w3.mul(&y.c.getb());
 
-            let mut ta = FP8::new_copy(&self.a.geta());
-            let mut tb = FP8::new_copy(&y.a.geta());
+            let mut ta = self.a.geta();
+            let mut tb = y.a.geta();
             ta.add(&self.a.getb());
             ta.norm();
             tb.add(&y.a.getb());
             tb.norm();
-            let mut tc = FP8::new_copy(&ta);
+            let mut tc = ta.clone();
             tc.mul(&tb);
-            let mut t = FP8::new_copy(&w1);
+            let mut t = w1.clone();
             t.add(&w2);
             t.neg();
             tc.add(&t);
 
-            ta.copy(&self.a.geta());
+            ta = self.a.geta();
             ta.add(&self.c.getb());
             ta.norm();
-            tb.copy(&y.a.geta());
+            tb = y.a.geta();
             tb.add(&y.c.getb());
             tb.norm();
-            let mut td = FP8::new_copy(&ta);
+            let mut td = ta.clone();
             td.mul(&tb);
-            t.copy(&w1);
+            t = w1.clone();
             t.add(&w3);
             t.neg();
             td.add(&t);
 
-            ta.copy(&self.a.getb());
+            ta = self.a.getb();
             ta.add(&self.c.getb());
             ta.norm();
-            tb.copy(&y.a.getb());
+            tb = y.a.getb();
             tb.add(&y.c.getb());
             tb.norm();
-            let mut te = FP8::new_copy(&ta);
+            let mut te = ta.clone();
             te.mul(&tb);
-            t.copy(&w2);
+            t = w2.clone();
             t.add(&w3);
             t.neg();
             te.add(&t);
@@ -727,10 +693,9 @@ impl FP48 {
 
     /* self=1/self */
     pub fn inverse(&mut self) {
-        let mut f0 = FP16::new_copy(&self.a);
-        let mut f1 = FP16::new_copy(&self.b);
-        let mut f2 = FP16::new_copy(&self.a);
-        let mut f3 = FP16::new();
+        let mut f0 = self.geta();
+        let mut f1 = self.getb();
+        let mut f2 = self.geta();
 
         //self.norm();
         f0.sqr();
@@ -739,21 +704,21 @@ impl FP48 {
         f0.sub(&f1);
         f0.norm();
 
-        f1.copy(&self.c);
+        f1 = self.getc();
         f1.sqr();
         f1.times_i();
         f2.mul(&self.b);
         f1.sub(&f2);
         f1.norm();
 
-        f2.copy(&self.b);
+        f2 = self.getb();
         f2.sqr();
-        f3.copy(&self.a);
+        let mut f3 = self.geta();
         f3.mul(&self.c);
         f2.sub(&f3);
         f2.norm();
 
-        f3.copy(&self.b);
+        f3 = self.getb();
         f3.mul(&f2);
         f3.times_i();
         self.a.mul(&f0);
@@ -764,19 +729,19 @@ impl FP48 {
         f3.add(&self.c);
         f3.norm();
         f3.inverse();
-        self.a.copy(&f0);
+        self.a = f0;
         self.a.mul(&f3);
-        self.b.copy(&f1);
+        self.b = f1;
         self.b.mul(&f3);
-        self.c.copy(&f2);
+        self.c = f2;
         self.c.mul(&f3);
         self.stype = DENSE;
     }
 
     /* self=self^p using Frobenius */
     pub fn frob(&mut self, f: &FP2, n: isize) {
-        let mut f2 = FP2::new_copy(f);
-        let mut f3 = FP2::new_copy(f);
+        let mut f2 = f.clone();
+        let mut f3 = f.clone();
 
         f2.sqr();
         f3.mul(&f2);
@@ -802,16 +767,15 @@ impl FP48 {
         self.stype = DENSE;
     }
 
-    /* trace function */
+    /// Trace function
     pub fn trace(&mut self) -> FP16 {
-        let mut t = FP16::new();
-        t.copy(&self.a);
+        let mut t = self.geta();
         t.imul(3);
         t.reduce();
-        return t;
+        t
     }
 
-    /* convert from byte array to FP48 */
+    /// Convert from byte array to FP48
     pub fn frombytes(w: &[u8]) -> FP48 {
         let mut t: [u8; big::MODBYTES as usize] = [0; big::MODBYTES as usize];
         let mb = big::MODBYTES as usize;
@@ -819,290 +783,288 @@ impl FP48 {
         for i in 0..mb {
             t[i] = w[i]
         }
-        let mut a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + mb]
         }
-        let mut b = Big::frombytes(&t);
-        let mut c = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 2 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 3 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        let mut d = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        let mut ea = FP4::new_fp2s(&c, &d);
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 4 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 5 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 6 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 7 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        let mut eb = FP4::new_fp2s(&c, &d);
+        let eb = FP4::new_fp2s(c, d);
 
-        let mut ea8 = FP8::new_fp4s(&ea, &eb);
+        let ea8 = FP8::new_fp4s(ea, eb);
 
         for i in 0..mb {
             t[i] = w[i + 8 * mb]
         }
-        let mut a = Big::frombytes(&t);
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 9 * mb]
         }
-        let mut b = Big::frombytes(&t);
-        let mut c = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 10 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 11 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        let mut d = FP2::new_bigs(&a, &b);
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        ea.copy(&FP4::new_fp2s(&c, &d));
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 12 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 13 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 14 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 15 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        eb.copy(&FP4::new_fp2s(&c, &d));
+        let eb = FP4::new_fp2s(c, d);
 
-        let mut eb8 = FP8::new_fp4s(&ea, &eb);
+        let eb8 = FP8::new_fp4s(ea, eb);
 
-        let e = FP16::new_fp8s(&ea8, &eb8);
+        let e = FP16::new_fp8s(ea8, eb8);
 
         for i in 0..mb {
             t[i] = w[i + 16 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 17 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 18 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 19 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        ea.copy(&FP4::new_fp2s(&c, &d));
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 20 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 21 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 22 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 23 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        eb.copy(&FP4::new_fp2s(&c, &d));
+        let eb = FP4::new_fp2s(c, d);
 
-        ea8.copy(&FP8::new_fp4s(&ea, &eb));
+        let ea8 = FP8::new_fp4s(ea, eb);
 
         for i in 0..mb {
             t[i] = w[i + 24 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 25 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 26 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 27 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        ea.copy(&FP4::new_fp2s(&c, &d));
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 28 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 29 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 30 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 31 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        eb.copy(&FP4::new_fp2s(&c, &d));
+        let eb = FP4::new_fp2s(c, d);
 
-        eb8.copy(&FP8::new_fp4s(&ea, &eb));
+        let eb8 = FP8::new_fp4s(ea, eb);
 
-        let f = FP16::new_fp8s(&ea8, &eb8);
+        let f = FP16::new_fp8s(ea8, eb8);
 
         for i in 0..mb {
             t[i] = w[i + 32 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 33 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 34 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 35 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        ea.copy(&FP4::new_fp2s(&c, &d));
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 36 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 37 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-
-        c.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 38 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 39 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        eb.copy(&FP4::new_fp2s(&c, &d));
+        let eb = FP4::new_fp2s(c, d);
 
-        ea8.copy(&FP8::new_fp4s(&ea, &eb));
+        let ea8 = FP8::new_fp4s(ea, eb);
 
         for i in 0..mb {
             t[i] = w[i + 40 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 41 * mb]
         }
-        b.copy(&Big::frombytes(&t));
+        let b = Big::frombytes(&t);
 
-        c.copy(&FP2::new_bigs(&a, &b));
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 42 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 43 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        ea.copy(&FP4::new_fp2s(&c, &d));
+        let ea = FP4::new_fp2s(c, d);
 
         for i in 0..mb {
             t[i] = w[i + 44 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 45 * mb]
         }
-        b.copy(&Big::frombytes(&t));
+        let b = Big::frombytes(&t);
 
-        c.copy(&FP2::new_bigs(&a, &b));
+        let c = FP2::new_bigs(a, b);
 
         for i in 0..mb {
             t[i] = w[i + 46 * mb]
         }
-        a.copy(&Big::frombytes(&t));
+        let a = Big::frombytes(&t);
         for i in 0..mb {
             t[i] = w[i + 47 * mb]
         }
-        b.copy(&Big::frombytes(&t));
-        d.copy(&FP2::new_bigs(&a, &b));
+        let b = Big::frombytes(&t);
+        let d = FP2::new_bigs(a, b);
 
-        eb.copy(&FP4::new_fp2s(&c, &d));
+        let eb = FP4::new_fp2s(c, d);
 
-        eb8.copy(&FP8::new_fp4s(&ea, &eb));
+        let eb8 = FP8::new_fp4s(ea, eb);
 
-        let g = FP16::new_fp8s(&ea8, &eb8);
+        let g = FP16::new_fp8s(ea8, eb8);
 
-        return FP48::new_fp16s(&e, &f, &g);
+        return FP48::new_fp16s(e, f, g);
     }
 
     /* convert this to byte array */
@@ -1327,14 +1289,14 @@ impl FP48 {
 
     /* self=self^e */
     pub fn pow(&self, e: &Big) -> FP48 {
-        let mut r = FP48::new_copy(self);
+        let mut r = self.clone();
         r.norm();
-        let mut e1 = Big::new_copy(e);
+        let mut e1 = e.clone();
         e1.norm();
-        let mut e3 = Big::new_copy(&e1);
+        let mut e3 = e1.clone();
         e3.pmul(3);
         e3.norm();
-        let mut w = FP48::new_copy(&r);
+        let mut w = r.clone();
 
         let nb = e3.nbits();
         for i in (1..nb - 1).rev() {
@@ -1354,34 +1316,33 @@ impl FP48 {
         return w;
     }
 
-    /* constant time powering by small integer of max length bts */
+    /// Constant time powering by small integer of max length bts
     pub fn pinpow(&mut self, e: i32, bts: i32) {
-        let mut r: [FP48; 2] = [FP48::new_int(1), FP48::new_copy(self)];
-        let mut t = FP48::new();
+        let mut r: [FP48; 2] = [FP48::new_int(1), self.clone()];
 
         for i in (0..bts).rev() {
             let b: usize = ((e >> i) & 1) as usize;
-            t.copy(&r[b]);
+            let t = r[b].clone();
             r[1 - b].mul(&t);
             r[b].usqr();
         }
-        self.copy(&r[0]);
+        *self = r[0].clone();
     }
 
     pub fn compow(&mut self, e: &Big, r: &Big) -> FP16 {
-        let f = FP2::new_bigs(&Big::new_ints(&rom::FRA), &Big::new_ints(&rom::FRB));
+        let f = FP2::new_bigs(Big::new_ints(&rom::FRA), Big::new_ints(&rom::FRB));
         let q = Big::new_ints(&rom::MODULUS);
 
-        let mut g1 = FP48::new_copy(self);
-        let mut g2 = FP48::new_copy(self);
+        let mut g1 = self.clone();
+        let mut g2 = self.clone();
 
-        let mut m = Big::new_copy(&q);
+        let mut m = q.clone();
         m.rmod(&r);
 
-        let mut a = Big::new_copy(&e);
+        let mut a = e.clone();
         a.rmod(&mut m);
 
-        let mut b = Big::new_copy(&e);
+        let mut b = e.clone();
         b.div(&mut m);
 
         let mut c = g1.trace();
@@ -1450,7 +1411,6 @@ impl FP48 {
             FP48::new(),
         ];
 
-        let mut r = FP48::new();
         let mut p = FP48::new();
         const CT: usize = 1 + big::NLEN * (big::BASEBITS as usize);
         let mut w1: [i8; CT] = [0; CT];
@@ -1464,22 +1424,22 @@ impl FP48 {
 
         let mut mt = Big::new();
         let mut t: [Big; 16] = [
-            Big::new_copy(&u[0]),
-            Big::new_copy(&u[1]),
-            Big::new_copy(&u[2]),
-            Big::new_copy(&u[3]),
-            Big::new_copy(&u[4]),
-            Big::new_copy(&u[5]),
-            Big::new_copy(&u[6]),
-            Big::new_copy(&u[7]),
-            Big::new_copy(&u[8]),
-            Big::new_copy(&u[9]),
-            Big::new_copy(&u[10]),
-            Big::new_copy(&u[11]),
-            Big::new_copy(&u[12]),
-            Big::new_copy(&u[13]),
-            Big::new_copy(&u[14]),
-            Big::new_copy(&u[15]),
+            u[0].clone(),
+            u[1].clone(),
+            u[2].clone(),
+            u[3].clone(),
+            u[4].clone(),
+            u[5].clone(),
+            u[6].clone(),
+            u[7].clone(),
+            u[8].clone(),
+            u[9].clone(),
+            u[10].clone(),
+            u[11].clone(),
+            u[12].clone(),
+            u[13].clone(),
+            u[14].clone(),
+            u[15].clone(),
         ];
 
         for i in 0..16 {
@@ -1487,36 +1447,36 @@ impl FP48 {
         }
 
         // precomputation
-        g1[0].copy(&q[0]);
-        r.copy(&g1[0]);
-        g1[1].copy(&r);
+        g1[0] = q[0].clone();
+        let mut r = g1[0].clone();
+        g1[1] = r.clone();
         g1[1].mul(&q[1]); // q[0].q[1]
-        g1[2].copy(&r);
+        g1[2] = r.clone();
         g1[2].mul(&q[2]);
-        r.copy(&g1[1]); // q[0].q[2]
-        g1[3].copy(&r);
+        r = g1[1].clone(); // q[0].q[2]
+        g1[3] = r.clone();
         g1[3].mul(&q[2]);
-        r.copy(&g1[0]); // q[0].q[1].q[2]
-        g1[4].copy(&r);
+        r = g1[0].clone(); // q[0].q[1].q[2]
+        g1[4] = r.clone();
         g1[4].mul(&q[3]);
-        r.copy(&g1[1]); // q[0].q[3]
-        g1[5].copy(&r);
+        r = g1[1].clone(); // q[0].q[3]
+        g1[5] = r.clone();
         g1[5].mul(&q[3]);
-        r.copy(&g1[2]); // q[0].q[1].q[3]
-        g1[6].copy(&r);
+        r = g1[2].clone(); // q[0].q[1].q[3]
+        g1[6] = r.clone();
         g1[6].mul(&q[3]);
-        r.copy(&g1[3]); // q[0].q[2].q[3]
-        g1[7].copy(&r);
+        r = g1[3].clone(); // q[0].q[2].q[3]
+        g1[7] = r.clone();
         g1[7].mul(&q[3]); // q[0].q[1].q[2].q[3]
 
         // Use Frobenius
-        let f = FP2::new_bigs(&Big::new_ints(&rom::FRA), &Big::new_ints(&rom::FRB));
+        let f = FP2::new_bigs(Big::new_ints(&rom::FRA), Big::new_ints(&rom::FRB));
         for i in 0..8 {
-            g2[i].copy(&g1[i]);
+            g2[i] = g1[i].clone();
             g2[i].frob(&f, 4);
-            g3[i].copy(&g2[i]);
+            g3[i] = g2[i].clone();
             g3[i].frob(&f, 4);
-            g4[i].copy(&g3[i]);
+            g4[i] = g3[i].clone();
             g4[i].frob(&f, 4);
         }
 
@@ -1630,22 +1590,22 @@ impl FP48 {
         }
 
         // apply correction
-        r.copy(&q[0]);
+        r = q[0].clone();
         r.conj();
         r.mul(&p);
         p.cmove(&r, pb1);
 
-        r.copy(&q[4]);
+        r = q[4].clone();
         r.conj();
         r.mul(&p);
         p.cmove(&r, pb2);
 
-        r.copy(&q[8]);
+        r = q[8].clone();
         r.conj();
         r.mul(&p);
         p.cmove(&r, pb3);
 
-        r.copy(&q[12]);
+        r = q[12].clone();
         r.conj();
         r.mul(&p);
         p.cmove(&r, pb4);
diff --git a/src/fp8.rs b/src/fp8.rs
index ab4bedf..b8cac70 100644
--- a/src/fp8.rs
+++ b/src/fp8.rs
@@ -23,7 +23,7 @@ use super::fp2::FP2;
 use super::fp4::FP4;
 //use std::str::SplitWhitespace;
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub struct FP8 {
     a: FP4,
     b: FP4,
@@ -38,45 +38,32 @@ impl FP8 {
     }
 
     pub fn new_int(a: isize) -> FP8 {
-        let mut f = FP8::new();
-        f.a.copy(&FP4::new_int(a));
-        f.b.zero();
-        return f;
-    }
-
-    pub fn new_copy(x: &FP8) -> FP8 {
-        let mut f = FP8::new();
-        f.a.copy(&x.a);
-        f.b.copy(&x.b);
-        return f;
+        FP8 {
+            a: FP4::new_int(a),
+            b: FP4::new(),
+        }
     }
 
-    pub fn new_fp4s(c: &FP4, d: &FP4) -> FP8 {
-        let mut f = FP8::new();
-        f.a.copy(c);
-        f.b.copy(d);
-        return f;
+    pub fn new_fp4s(a: FP4, b: FP4) -> FP8 {
+        FP8 { a, b }
     }
 
-    pub fn new_fp4(c: &FP4) -> FP8 {
-        let mut f = FP8::new();
-        f.a.copy(c);
-        f.b.zero();
-        return f;
+    pub fn new_fp4(a: FP4) -> FP8 {
+        FP8 { a, b: FP4::new() }
     }
 
     pub fn set_fp4s(&mut self, c: &FP4, d: &FP4) {
-        self.a.copy(&c);
-        self.b.copy(&d);
+        self.a = c.clone();
+        self.b = d.clone();
     }
 
     pub fn set_fp4(&mut self, c: &FP4) {
-        self.a.copy(&c);
+        self.a = c.clone();
         self.b.zero();
     }
 
     pub fn set_fp4h(&mut self, c: &FP4) {
-        self.b.copy(&c);
+        self.b = c.clone();
         self.a.zero();
     }
 
@@ -114,31 +101,22 @@ impl FP8 {
     }
     /* extract real part a */
     pub fn real(&self) -> FP4 {
-        let f = FP4::new_copy(&self.a);
-        return f;
+        self.geta()
     }
 
     pub fn geta(&self) -> FP4 {
-        return self.a;
-        //        let f = FP4::new_copy(&self.a);
-        //        return f;
+        self.a.clone()
     }
+
     /* extract imaginary part b */
     pub fn getb(&self) -> FP4 {
-        return self.b;
-        //        let f = FP4::new_copy(&self.b);
-        //        return f;
+        self.b.clone()
     }
 
     /* test self=x */
     pub fn equals(&self, x: &FP8) -> bool {
         return self.a.equals(&x.a) && self.b.equals(&x.b);
     }
-    /* copy self=x */
-    pub fn copy(&mut self, x: &FP8) {
-        self.a.copy(&x.a);
-        self.b.copy(&x.b);
-    }
 
     /* set self=0 */
     pub fn zero(&mut self) {
@@ -155,17 +133,16 @@ impl FP8 {
     /* negate self mod Modulus */
     pub fn neg(&mut self) {
         self.norm();
-        let mut m = FP4::new_copy(&self.a);
-        let mut t = FP4::new();
+        let mut m = self.geta();
 
         m.add(&self.b);
         m.neg();
 
-        t.copy(&m);
+        let mut t = m.clone();
         t.add(&self.b);
-        self.b.copy(&m);
+        self.b = m.clone();
         self.b.add(&self.a);
-        self.a.copy(&t);
+        self.a = t.clone();
         self.norm();
     }
 
@@ -198,7 +175,7 @@ impl FP8 {
 
     /* self-=a */
     pub fn sub(&mut self, x: &FP8) {
-        let mut m = FP8::new_copy(x);
+        let mut m = x.clone();
         m.neg();
         self.add(&m);
     }
@@ -236,9 +213,9 @@ impl FP8 {
     /* self*=self */
 
     pub fn sqr(&mut self) {
-        let mut t1 = FP4::new_copy(&self.a);
-        let mut t2 = FP4::new_copy(&self.b);
-        let mut t3 = FP4::new_copy(&self.a);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
+        let mut t3 = self.geta();
 
         t3.mul(&self.b);
         t1.add(&self.b);
@@ -249,11 +226,11 @@ impl FP8 {
         t1.norm();
         t2.norm();
 
-        self.a.copy(&t1);
+        self.a = t1.clone();
 
         self.a.mul(&t2);
 
-        t2.copy(&t3);
+        t2 = t3.clone();
         t2.times_i();
         t2.add(&t3);
         t2.norm();
@@ -261,7 +238,7 @@ impl FP8 {
         self.a.add(&t2);
 
         t3.dbl();
-        self.b.copy(&t3);
+        self.b = t3.clone();
 
         self.norm();
     }
@@ -270,14 +247,13 @@ impl FP8 {
     pub fn mul(&mut self, y: &FP8) {
         //self.norm();
 
-        let mut t1 = FP4::new_copy(&self.a);
-        let mut t2 = FP4::new_copy(&self.b);
-        let mut t3 = FP4::new();
-        let mut t4 = FP4::new_copy(&self.b);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
+        let mut t3 = y.getb();
+        let mut t4 = self.getb();
 
         t1.mul(&y.a);
         t2.mul(&y.b);
-        t3.copy(&y.b);
         t3.add(&y.a);
         t4.add(&self.a);
 
@@ -286,18 +262,18 @@ impl FP8 {
 
         t4.mul(&t3);
 
-        t3.copy(&t1);
+        t3 = t1.clone();
         t3.neg();
         t4.add(&t3);
         t4.norm();
 
-        t3.copy(&t2);
+        t3 = t2.clone();
         t3.neg();
-        self.b.copy(&t4);
+        self.b = t4.clone();
         self.b.add(&t3);
 
         t2.times_i();
-        self.a.copy(&t2);
+        self.a = t2.clone();
         self.a.add(&t1);
 
         self.norm();
@@ -312,8 +288,8 @@ impl FP8 {
     pub fn inverse(&mut self) {
         //self.norm();
 
-        let mut t1 = FP4::new_copy(&self.a);
-        let mut t2 = FP4::new_copy(&self.b);
+        let mut t1 = self.geta();
+        let mut t2 = self.getb();
 
         t1.sqr();
         t2.sqr();
@@ -330,11 +306,11 @@ impl FP8 {
 
     /* self*=i where i = sqrt(-1+sqrt(-1)) */
     pub fn times_i(&mut self) {
-        let mut s = FP4::new_copy(&self.b);
-        let t = FP4::new_copy(&self.a);
+        let mut s = self.getb();
+        let t = self.geta();
         s.times_i();
-        self.a.copy(&s);
-        self.b.copy(&t);
+        self.a = s.clone();
+        self.b = t.clone();
 
         self.norm();
     }
@@ -346,7 +322,7 @@ impl FP8 {
 
     /* self=self^p using Frobenius */
     pub fn frob(&mut self, f: &FP2) {
-        let mut ff = FP2::new_copy(f);
+        let mut ff = f.clone();
         ff.sqr();
         ff.mul_ip();
         ff.norm();
@@ -358,9 +334,9 @@ impl FP8 {
 
     /* self=self^e */
     pub fn pow(&self, e: &Big) -> FP8 {
-        let mut w = FP8::new_copy(self);
+        let mut w = self.clone();
         w.norm();
-        let mut z = Big::new_copy(&e);
+        let mut z = e.clone();
         let mut r = FP8::new_int(1);
         z.norm();
         loop {
@@ -380,8 +356,8 @@ impl FP8 {
 
     /* XTR xtr_a function */
     pub fn xtr_a(&mut self, w: &FP8, y: &FP8, z: &FP8) {
-        let mut r = FP8::new_copy(w);
-        let mut t = FP8::new_copy(w);
+        let mut r = w.clone();
+        let mut t = w.clone();
 
         r.sub(y);
         r.norm();
@@ -391,7 +367,7 @@ impl FP8 {
         t.pmul(&self.b);
         t.times_i();
 
-        self.copy(&r);
+        *self = r.clone();
         self.add(&t);
         self.add(z);
 
@@ -400,7 +376,7 @@ impl FP8 {
 
     /* XTR xtr_d function */
     pub fn xtr_d(&mut self) {
-        let mut w = FP8::new_copy(self);
+        let mut w = self.clone();
         self.sqr();
         w.conj();
         w.dbl();
@@ -411,17 +387,15 @@ impl FP8 {
 
     /* r=x^n using XTR method on traces of FP24s */
     pub fn xtr_pow(&self, n: &Big) -> FP8 {
-        let mut sf = FP8::new_copy(self);
+        let mut sf = self.clone();
         sf.norm();
         let mut a = FP8::new_int(3);
-        let mut b = FP8::new_copy(&sf);
-        let mut c = FP8::new_copy(&b);
+        let mut b = sf.clone();
+        let mut c = b.clone();
         c.xtr_d();
-        let mut t = FP8::new();
-        let mut r = FP8::new();
 
         let par = n.parity();
-        let mut v = Big::new_copy(n);
+        let mut v = n.clone();
         v.norm();
         v.fshr(1);
         if par == 0 {
@@ -432,46 +406,39 @@ impl FP8 {
         let nb = v.nbits();
         for i in (0..nb).rev() {
             if v.bit(i) != 1 {
-                t.copy(&b);
+                let t = b.clone();
                 sf.conj();
                 c.conj();
                 b.xtr_a(&a, &sf, &c);
                 sf.conj();
-                c.copy(&t);
+                c = t.clone();
                 c.xtr_d();
                 a.xtr_d();
             } else {
-                t.copy(&a);
+                let mut t = a.clone();
                 t.conj();
-                a.copy(&b);
+                a = b.clone();
                 a.xtr_d();
                 b.xtr_a(&c, &sf, &t);
                 c.xtr_d();
             }
         }
-        if par == 0 {
-            r.copy(&c)
-        } else {
-            r.copy(&b)
-        }
+        let mut r = if par == 0 { c.clone() } else { b.clone() };
         r.reduce();
-        return r;
+        r
     }
 
     /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
     pub fn xtr_pow2(&mut self, ck: &FP8, ckml: &FP8, ckm2l: &FP8, a: &Big, b: &Big) -> FP8 {
-        let mut e = Big::new_copy(a);
-        let mut d = Big::new_copy(b);
-        let mut w = Big::new();
+        let mut e = a.clone();
+        let mut d = b.clone();
         e.norm();
         d.norm();
 
-        let mut cu = FP8::new_copy(ck); // can probably be passed in w/o copying
-        let mut cv = FP8::new_copy(self);
-        let mut cumv = FP8::new_copy(ckml);
-        let mut cum2v = FP8::new_copy(ckm2l);
-        let mut r = FP8::new();
-        let mut t = FP8::new();
+        let mut cu = ck.clone(); // can probably be passed in w/o copying
+        let mut cv = self.clone();
+        let mut cumv = ckml.clone();
+        let mut cum2v = ckm2l.clone();
 
         let mut f2: usize = 0;
         while d.parity() == 0 && e.parity() == 0 {
@@ -482,125 +449,125 @@ impl FP8 {
 
         while Big::comp(&d, &e) != 0 {
             if Big::comp(&d, &e) > 0 {
-                w.copy(&e);
+                let mut w = e.clone();
                 w.imul(4);
                 w.norm();
                 if Big::comp(&d, &w) <= 0 {
-                    w.copy(&d);
-                    d.copy(&e);
+                    w = d.clone();
+                    d = e.clone();
                     e.rsub(&w);
                     e.norm();
 
-                    t.copy(&cv);
+                    let mut t = cv.clone();
                     t.xtr_a(&cu, &cumv, &cum2v);
-                    cum2v.copy(&cumv);
+                    cum2v = cumv.clone();
                     cum2v.conj();
-                    cumv.copy(&cv);
-                    cv.copy(&cu);
-                    cu.copy(&t);
+                    cumv = cv.clone();
+                    cv = cu.clone();
+                    cu = t.clone();
                 } else {
                     if d.parity() == 0 {
                         d.fshr(1);
-                        r.copy(&cum2v);
+                        let mut r = cum2v.clone();
                         r.conj();
-                        t.copy(&cumv);
+                        let mut t = cumv.clone();
                         t.xtr_a(&cu, &cv, &r);
-                        cum2v.copy(&cumv);
+                        cum2v = cumv.clone();
                         cum2v.xtr_d();
-                        cumv.copy(&t);
+                        cumv = t.clone();
                         cu.xtr_d();
                     } else {
                         if e.parity() == 1 {
                             d.sub(&e);
                             d.norm();
                             d.fshr(1);
-                            t.copy(&cv);
+                            let mut t = cv.clone();
                             t.xtr_a(&cu, &cumv, &cum2v);
                             cu.xtr_d();
-                            cum2v.copy(&cv);
+                            cum2v = cv.clone();
                             cum2v.xtr_d();
                             cum2v.conj();
-                            cv.copy(&t);
+                            cv = t.clone();
                         } else {
-                            w.copy(&d);
-                            d.copy(&e);
+                            w = d.clone();
+                            d = e.clone();
                             d.fshr(1);
-                            e.copy(&w);
-                            t.copy(&cumv);
+                            e = w.clone();
+                            let mut t = cumv.clone();
                             t.xtr_d();
-                            cumv.copy(&cum2v);
+                            cumv = cum2v.clone();
                             cumv.conj();
-                            cum2v.copy(&t);
+                            cum2v = t.clone();
                             cum2v.conj();
-                            t.copy(&cv);
+                            t = cv.clone();
                             t.xtr_d();
-                            cv.copy(&cu);
-                            cu.copy(&t);
+                            cv = cu.clone();
+                            cu = t.clone();
                         }
                     }
                 }
             }
             if Big::comp(&d, &e) < 0 {
-                w.copy(&d);
+                let mut w = d.clone();
                 w.imul(4);
                 w.norm();
                 if Big::comp(&e, &w) <= 0 {
                     e.sub(&d);
                     e.norm();
-                    t.copy(&cv);
+                    let mut t = cv.clone();
                     t.xtr_a(&cu, &cumv, &cum2v);
-                    cum2v.copy(&cumv);
-                    cumv.copy(&cu);
-                    cu.copy(&t);
+                    cum2v = cumv.clone();
+                    cumv = cu.clone();
+                    cu = t.clone();
                 } else {
                     if e.parity() == 0 {
-                        w.copy(&d);
-                        d.copy(&e);
+                        w = d.clone();
+                        d = e.clone();
                         d.fshr(1);
-                        e.copy(&w);
-                        t.copy(&cumv);
+                        e = w.clone();
+                        let mut t = cumv.clone();
                         t.xtr_d();
-                        cumv.copy(&cum2v);
+                        cumv = cum2v.clone();
                         cumv.conj();
-                        cum2v.copy(&t);
+                        cum2v = t.clone();
                         cum2v.conj();
-                        t.copy(&cv);
+                        t = cv.clone();
                         t.xtr_d();
-                        cv.copy(&cu);
-                        cu.copy(&t);
+                        cv = cu.clone();
+                        cu = t.clone();
                     } else {
                         if d.parity() == 1 {
-                            w.copy(&e);
-                            e.copy(&d);
+                            w = e.clone();
+                            e = d.clone();
                             w.sub(&d);
                             w.norm();
-                            d.copy(&w);
+                            d = w.clone();
                             d.fshr(1);
-                            t.copy(&cv);
+                            let mut t = cv.clone();
                             t.xtr_a(&cu, &cumv, &cum2v);
                             cumv.conj();
-                            cum2v.copy(&cu);
+                            cum2v = cu.clone();
                             cum2v.xtr_d();
                             cum2v.conj();
-                            cu.copy(&cv);
+                            cu = cv.clone();
                             cu.xtr_d();
-                            cv.copy(&t);
+                            cv = t.clone();
                         } else {
                             d.fshr(1);
-                            r.copy(&cum2v);
+                            let mut r = cum2v.clone();
                             r.conj();
-                            t.copy(&cumv);
+                            let mut t = cumv.clone();
                             t.xtr_a(&cu, &cv, &r);
-                            cum2v.copy(&cumv);
+                            cum2v = cumv.clone();
                             cum2v.xtr_d();
-                            cumv.copy(&t);
+                            cumv = t.clone();
                             cu.xtr_d();
                         }
                     }
                 }
             }
         }
-        r.copy(&cv);
+        let mut r = cv.clone();
         r.xtr_a(&cu, &cumv, &cum2v);
         for _ in 0..f2 {
             r.xtr_d()
@@ -616,11 +583,11 @@ impl FP8 {
     }
 
     pub fn div_i(&mut self) {
-        let mut u = FP4::new_copy(&self.a);
-        let v = FP4::new_copy(&self.b);
+        let mut u = self.geta();
+        let v = self.getb();
         u.div_i();
-        self.a.copy(&v);
-        self.b.copy(&u);
+        self.a = v.clone();
+        self.b = u.clone();
     }
 
     pub fn div_i2(&mut self) {
@@ -629,13 +596,13 @@ impl FP8 {
     }
 
     pub fn div_2i(&mut self) {
-        let mut u = FP4::new_copy(&self.a);
-        let mut v = FP4::new_copy(&self.b);
+        let mut u = self.geta();
+        let mut v = self.getb();
         u.div_2i();
         v.dbl();
         v.norm();
-        self.a.copy(&v);
-        self.b.copy(&u);
+        self.a = v.clone();
+        self.b = u.clone();
     }
 
     /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
@@ -645,18 +612,18 @@ impl FP8 {
             return true;
         }
 
-        let mut a = FP4::new_copy(&self.a);
-        let mut s = FP4::new_copy(&self.b);
-        let mut t = FP4::new_copy(&self.a);
+        let mut a = self.geta();
+        let mut s = self.getb();
+        let mut t = self.geta();
 
         if s.iszilch() {
             if t.sqrt() {
-                self.a.copy(&t);
+                self.a = t.clone();
                 self.b.zero();
             } else {
                 t.div_i();
                 t.sqrt();
-                self.b.copy(&t);
+                self.b = t.clone();
                 self.a.zero();
             }
             return true;
@@ -667,18 +634,18 @@ impl FP8 {
         s.norm();
         a.sub(&s);
 
-        s.copy(&a);
+        s = a.clone();
         if !s.sqrt() {
             return false;
         }
 
-        a.copy(&t);
+        a = t.clone();
         a.add(&s);
         a.norm();
         a.div2();
 
         if !a.sqrt() {
-            a.copy(&t);
+            a = t.clone();
             a.sub(&s);
             a.norm();
             a.div2();
@@ -686,14 +653,14 @@ impl FP8 {
                 return false;
             }
         }
-        t.copy(&self.b);
-        s.copy(&a);
+        t = self.getb();
+        s = a.clone();
         s.add(&a);
         s.inverse();
 
         t.mul(&s);
-        self.a.copy(&a);
-        self.b.copy(&t);
+        self.a = a;
+        self.b = t;
 
         return true;
     }
diff --git a/src/mpin.rs b/src/mpin.rs
index 23b46a2..5d5a3da 100644
--- a/src/mpin.rs
+++ b/src/mpin.rs
@@ -191,7 +191,7 @@ pub fn today() -> usize {
 #[allow(non_snake_case)]
 fn emap(u: &Big, cb: isize) -> ECP {
     let mut P: ECP;
-    let mut x = Big::new_copy(u);
+    let mut x = u.clone();
     let p = Big::new_ints(&rom::MODULUS);
     x.rmod(&p);
     loop {
@@ -212,7 +212,7 @@ fn unmap(u: &mut Big, P: &mut ECP) -> isize {
     let mut R: ECP;
     let mut r = 0;
     let x = P.getx();
-    u.copy(&x);
+    *u = x.clone();
     loop {
         u.dec(1);
         u.norm();
@@ -739,13 +739,13 @@ pub fn kangaroo(e: &[u8], f: &[u8]) -> isize {
     let mut ge = FP12::frombytes(e);
     let mut gf = FP12::frombytes(f);
     let mut distance: [isize; TS] = [0; TS];
-    let mut t = FP12::new_copy(&gf);
+    let mut t = gf.clone();
 
-    let mut table: [FP12; TS] = [FP12::new(); TS];
+    let mut table: Vec<FP12> = Vec::with_capacity(TS);
     let mut s: isize = 1;
     for m in 0..TS {
         distance[m] = s;
-        table[m] = FP12::new_copy(&t);
+        table.push(t.clone());
         s *= 2;
         t.usqr();
     }
@@ -757,7 +757,7 @@ pub fn kangaroo(e: &[u8], f: &[u8]) -> isize {
         t.mul(&table[i]);
         dn += distance[i];
     }
-    gf.copy(&t);
+    gf = t.clone();
     gf.conj();
     let mut steps: usize = 0;
     let mut dm: isize = 0;
@@ -910,12 +910,11 @@ pub fn server_key(
         return INVALID_POINT;
     }
 
-    let mut U = ECP::new();
-    if let Some(rxcid) = xcid {
-        U.copy(&ECP::frombytes(&rxcid));
+    let mut U = if let Some(rxcid) = xcid {
+        ECP::frombytes(&rxcid)
     } else {
-        U.copy(&ECP::frombytes(&xid));
-    }
+        ECP::frombytes(&xid)
+    };
 
     if U.is_infinity() {
         return INVALID_POINT;
@@ -934,7 +933,7 @@ pub fn server_key(
 
     hash(sha, &mut c, &mut U, sk);
 
-    return 0;
+    0
 }
 
 #[cfg(test)]
diff --git a/src/mpin192.rs b/src/mpin192.rs
index a8a40b0..43758a7 100644
--- a/src/mpin192.rs
+++ b/src/mpin192.rs
@@ -207,7 +207,7 @@ pub fn today() -> usize {
 #[allow(non_snake_case)]
 fn emap(u: &Big, cb: isize) -> ECP {
     let mut P: ECP;
-    let mut x = Big::new_copy(u);
+    let mut x = u.clone();
     let mut p = Big::new_ints(&rom::MODULUS);
     x.rmod(&mut p);
     loop {
@@ -228,7 +228,7 @@ fn unmap(u: &mut Big, P: &mut ECP) -> isize {
     let mut R: ECP;
     let mut r = 0;
     let x = P.getx();
-    u.copy(&x);
+    *u = x.clone();
     loop {
         u.dec(1);
         u.norm();
@@ -754,13 +754,13 @@ pub fn kangaroo(e: &[u8], f: &[u8]) -> isize {
     let mut ge = FP24::frombytes(e);
     let mut gf = FP24::frombytes(f);
     let mut distance: [isize; TS] = [0; TS];
-    let mut t = FP24::new_copy(&gf);
+    let mut t = gf.clone();
 
-    let mut table: [FP24; TS] = [FP24::new(); TS];
+    let mut table: Vec<FP24> = Vec::with_capacity(TS);
     let mut s: isize = 1;
     for m in 0..TS {
         distance[m] = s;
-        table[m] = FP24::new_copy(&t);
+        table.push(t.clone());
         s *= 2;
         t.usqr();
     }
@@ -772,7 +772,7 @@ pub fn kangaroo(e: &[u8], f: &[u8]) -> isize {
         t.mul(&mut table[i]);
         dn += distance[i];
     }
-    gf.copy(&t);
+    gf = t.clone();
     gf.conj();
     let mut steps: usize = 0;
     let mut dm: isize = 0;
@@ -925,12 +925,11 @@ pub fn server_key(
         return INVALID_POINT;
     }
 
-    let mut U = ECP::new();
-    if let Some(rxcid) = xcid {
-        U.copy(&ECP::frombytes(&rxcid));
+    let mut U = if let Some(rxcid) = xcid {
+        ECP::frombytes(&rxcid)
     } else {
-        U.copy(&ECP::frombytes(&xid));
-    }
+        ECP::frombytes(&xid)
+    };
 
     if U.is_infinity() {
         return INVALID_POINT;
diff --git a/src/mpin256.rs b/src/mpin256.rs
index 22db48e..0e5e960 100644
--- a/src/mpin256.rs
+++ b/src/mpin256.rs
@@ -240,7 +240,7 @@ pub fn today() -> usize {
 #[allow(non_snake_case)]
 fn emap(u: &Big, cb: isize) -> ECP {
     let mut P: ECP;
-    let mut x = Big::new_copy(u);
+    let mut x = u.clone();
     let mut p = Big::new_ints(&rom::MODULUS);
     x.rmod(&mut p);
     loop {
@@ -261,7 +261,7 @@ fn unmap(u: &mut Big, P: &mut ECP) -> isize {
     let mut R: ECP;
     let mut r = 0;
     let x = P.getx();
-    u.copy(&x);
+    *u = x.clone();
     loop {
         u.dec(1);
         u.norm();
@@ -788,13 +788,13 @@ pub fn kangaroo(e: &[u8], f: &[u8]) -> isize {
     let mut ge = FP48::frombytes(e);
     let mut gf = FP48::frombytes(f);
     let mut distance: [isize; TS] = [0; TS];
-    let mut t = FP48::new_copy(&gf);
+    let mut t = gf.clone();
 
-    let mut table: [FP48; TS] = [FP48::new(); TS];
... 1950 lines suppressed ...