github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpn/t-matrix22.c (about)

     1  /* Tests matrix22_mul.
     2  
     3  Copyright 2008 Free Software Foundation, Inc.
     4  
     5  This file is part of the GNU MP Library test suite.
     6  
     7  The GNU MP Library test suite is free software; you can redistribute it
     8  and/or modify it under the terms of the GNU General Public License as
     9  published by the Free Software Foundation; either version 3 of the License,
    10  or (at your option) any later version.
    11  
    12  The GNU MP Library test suite is distributed in the hope that it will be
    13  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
    15  Public License for more details.
    16  
    17  You should have received a copy of the GNU General Public License along with
    18  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
    19  
    20  #include <stdio.h>
    21  #include <stdlib.h>
    22  
    23  #include "gmp.h"
    24  #include "gmp-impl.h"
    25  #include "tests.h"
    26  
    27  struct matrix {
    28    mp_size_t alloc;
    29    mp_size_t n;
    30    mp_ptr e00, e01, e10, e11;
    31  };
    32  
    33  static void
    34  matrix_init (struct matrix *M, mp_size_t n)
    35  {
    36    mp_ptr p = refmpn_malloc_limbs (4*(n+1));
    37    M->e00 = p; p += n+1;
    38    M->e01 = p; p += n+1;
    39    M->e10 = p; p += n+1;
    40    M->e11 = p;
    41    M->alloc = n + 1;
    42    M->n = 0;
    43  }
    44  
    45  static void
    46  matrix_clear (struct matrix *M)
    47  {
    48    refmpn_free_limbs (M->e00);
    49  }
    50  
    51  static void
    52  matrix_copy (struct matrix *R, const struct matrix *M)
    53  {
    54    R->n = M->n;
    55    MPN_COPY (R->e00, M->e00, M->n);
    56    MPN_COPY (R->e01, M->e01, M->n);
    57    MPN_COPY (R->e10, M->e10, M->n);
    58    MPN_COPY (R->e11, M->e11, M->n);
    59  }
    60  
    61  /* Used with same size, so no need for normalization. */
    62  static int
    63  matrix_equal_p (const struct matrix *A, const struct matrix *B)
    64  {
    65    return (A->n == B->n
    66  	  && mpn_cmp (A->e00, B->e00, A->n) == 0
    67  	  && mpn_cmp (A->e01, B->e01, A->n) == 0
    68  	  && mpn_cmp (A->e10, B->e10, A->n) == 0
    69  	  && mpn_cmp (A->e11, B->e11, A->n) == 0);
    70  }
    71  
    72  static void
    73  matrix_random(struct matrix *M, mp_size_t n, gmp_randstate_ptr rands)
    74  {
    75    M->n = n;
    76    mpn_random (M->e00, n);
    77    mpn_random (M->e01, n);
    78    mpn_random (M->e10, n);
    79    mpn_random (M->e11, n);
    80  }
    81  
    82  #define MUL(rp, ap, an, bp, bn) do { \
    83      if (an > bn)		     \
    84        mpn_mul (rp, ap, an, bp, bn);  \
    85      else			     \
    86        mpn_mul (rp, bp, bn, ap, an);  \
    87    } while(0)
    88  
    89  static void
    90  ref_matrix22_mul (struct matrix *R,
    91  		  const struct matrix *A,
    92  		  const struct matrix *B, mp_ptr tp)
    93  {
    94    mp_size_t an, bn, n;
    95    mp_ptr r00, r01, r10, r11, a00, a01, a10, a11, b00, b01, b10, b11;
    96  
    97    if (A->n >= B->n)
    98      {
    99        r00 = R->e00; a00 = A->e00; b00 = B->e00;
   100        r01 = R->e01; a01 = A->e01; b01 = B->e01;
   101        r10 = R->e10; a10 = A->e10; b10 = B->e10;
   102        r11 = R->e11; a11 = A->e11; b11 = B->e11;
   103        an = A->n, bn = B->n;
   104      }
   105    else
   106      {
   107        /* Transpose */
   108        r00 = R->e00; a00 = B->e00; b00 = A->e00;
   109        r01 = R->e10; a01 = B->e10; b01 = A->e10;
   110        r10 = R->e01; a10 = B->e01; b10 = A->e01;
   111        r11 = R->e11; a11 = B->e11; b11 = A->e11;
   112        an = B->n, bn = A->n;
   113      }
   114    n = an + bn;
   115    R->n = n + 1;
   116  
   117    mpn_mul (r00, a00, an, b00, bn);
   118    mpn_mul (tp, a01, an, b10, bn);
   119    r00[n] = mpn_add_n (r00, r00, tp, n);
   120  
   121    mpn_mul (r01, a00, an, b01, bn);
   122    mpn_mul (tp, a01, an, b11, bn);
   123    r01[n] = mpn_add_n (r01, r01, tp, n);
   124  
   125    mpn_mul (r10, a10, an, b00, bn);
   126    mpn_mul (tp, a11, an, b10, bn);
   127    r10[n] = mpn_add_n (r10, r10, tp, n);
   128  
   129    mpn_mul (r11, a10, an, b01, bn);
   130    mpn_mul (tp, a11, an, b11, bn);
   131    r11[n] = mpn_add_n (r11, r11, tp, n);
   132  }
   133  
   134  static void
   135  one_test (const struct matrix *A, const struct matrix *B, int i)
   136  {
   137    struct matrix R;
   138    struct matrix P;
   139    mp_ptr tp;
   140  
   141    matrix_init (&R, A->n + B->n + 1);
   142    matrix_init (&P, A->n + B->n + 1);
   143  
   144    tp = refmpn_malloc_limbs (mpn_matrix22_mul_itch (A->n, B->n));
   145  
   146    ref_matrix22_mul (&R, A, B, tp);
   147    matrix_copy (&P, A);
   148    mpn_matrix22_mul (P.e00, P.e01, P.e10, P.e11, A->n,
   149  		    B->e00, B->e01, B->e10, B->e11, B->n, tp);
   150    P.n = A->n + B->n + 1;
   151    if (!matrix_equal_p (&R, &P))
   152      {
   153        fprintf (stderr, "ERROR in test %d\n", i);
   154        gmp_fprintf (stderr, "A = (%Nx, %Nx\n      %Nx, %Nx)\n"
   155  		   "B = (%Nx, %Nx\n      %Nx, %Nx)\n"
   156  		   "R = (%Nx, %Nx (expected)\n      %Nx, %Nx)\n"
   157  		   "P = (%Nx, %Nx (incorrect)\n      %Nx, %Nx)\n",
   158  		   A->e00, A->n, A->e01, A->n, A->e10, A->n, A->e11, A->n,
   159  		   B->e00, B->n, B->e01, B->n, B->e10, B->n, B->e11, B->n,
   160  		   R.e00, R.n, R.e01, R.n, R.e10, R.n, R.e11, R.n,
   161  		   P.e00, P.n, P.e01, P.n, P.e10, P.n, P.e11, P.n);
   162        abort();
   163      }
   164    refmpn_free_limbs (tp);
   165    matrix_clear (&R);
   166    matrix_clear (&P);
   167  }
   168  
   169  #define MAX_SIZE (2+2*MATRIX22_STRASSEN_THRESHOLD)
   170  
   171  int
   172  main (int argc, char **argv)
   173  {
   174    struct matrix A;
   175    struct matrix B;
   176  
   177    gmp_randstate_ptr rands;
   178    mpz_t bs;
   179    int i;
   180  
   181    tests_start ();
   182    rands = RANDS;
   183  
   184    matrix_init (&A, MAX_SIZE);
   185    matrix_init (&B, MAX_SIZE);
   186    mpz_init (bs);
   187  
   188    for (i = 0; i < 1000; i++)
   189      {
   190        mp_size_t an, bn;
   191        mpz_urandomb (bs, rands, 32);
   192        an = 1 + mpz_get_ui (bs) % MAX_SIZE;
   193        mpz_urandomb (bs, rands, 32);
   194        bn = 1 + mpz_get_ui (bs) % MAX_SIZE;
   195  
   196        matrix_random (&A, an, rands);
   197        matrix_random (&B, bn, rands);
   198  
   199        one_test (&A, &B, i);
   200      }
   201    mpz_clear (bs);
   202    matrix_clear (&A);
   203    matrix_clear (&B);
   204  
   205    tests_end ();
   206    return 0;
   207  }