]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Replace 64 bits functions by generic methods.
authorBruno Turcksin <bruno.turcksin@gmail.com>
Tue, 26 Mar 2013 19:40:07 +0000 (19:40 +0000)
committerBruno Turcksin <bruno.turcksin@gmail.com>
Tue, 26 Mar 2013 19:40:07 +0000 (19:40 +0000)
git-svn-id: https://svn.dealii.org/branches/branch_bigger_global_dof_indices_4@29042 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/include/deal.II/lac/trilinos_sparse_matrix.h
deal.II/include/deal.II/lac/trilinos_sparsity_pattern.h
deal.II/include/deal.II/lac/trilinos_vector.h
deal.II/include/deal.II/lac/trilinos_vector_base.h
deal.II/source/lac/trilinos_precondition.cc
deal.II/source/lac/trilinos_sparse_matrix.cc
deal.II/source/lac/trilinos_sparsity_pattern.cc
deal.II/source/lac/trilinos_vector.cc
deal.II/source/lac/trilinos_vector_base.cc

index c44a0e1459b0547080484294299b9ee1de15417b..8c93853739b5c9f74adf4db0c36b7139da158253 100644 (file)
@@ -3027,8 +3027,13 @@ namespace TrilinosWrappers
   SparseMatrix::in_local_range (const size_type index) const
   {
     TrilinosWrappers::types::int_type begin, end;
-    begin = matrix->RowMap().MinMyGID64();
-    end = matrix->RowMap().MaxMyGID64()+1;
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    begin = matrix->RowMap().MinMyGID();
+    end = matrix->RowMap().MaxMyGID()+1;
+#else
+    begin = matrix->RowMap().MinMyGID();
+    end = matrix->RowMap().MaxMyGID()+1;
+#endif
 
     return ((index >= static_cast<size_type>(begin)) &&
             (index < static_cast<size_type>(end)));
@@ -3524,7 +3529,11 @@ namespace TrilinosWrappers
   SparseMatrix::size_type
   SparseMatrix::m () const
   {
-    return matrix -> NumGlobalRows64();
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    return matrix->NumGlobalRows();
+#else
+    return matrix->NumGlobalRows64();
+#endif
   }
 
 
@@ -3533,7 +3542,11 @@ namespace TrilinosWrappers
   SparseMatrix::size_type
   SparseMatrix::n () const
   {
-    return matrix -> NumGlobalCols64();
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    return matrix->NumGlobalCols();
+#else
+    return matrix->NumGlobalCols64();
+#endif
   }
 
 
@@ -3552,8 +3565,13 @@ namespace TrilinosWrappers
   SparseMatrix::local_range () const
   {
     size_type begin, end;
-    begin = matrix -> RowMap().MinMyGID64();
-    end = matrix -> RowMap().MaxMyGID64()+1;
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    begin = matrix->RowMap().MinMyGID();
+    end = matrix->RowMap().MaxMyGID()+1;
+#else
+    begin = matrix->RowMap().MinMyGID64();
+    end = matrix->RowMap().MaxMyGID64()+1;
+#endif
 
     return std::make_pair (begin, end);
   }
@@ -3564,7 +3582,11 @@ namespace TrilinosWrappers
   SparseMatrix::size_type
   SparseMatrix::n_nonzero_elements () const
   {
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    return matrix->NumGlobalNonzeros();
+#else
     return matrix->NumGlobalNonzeros64();
+#endif
   }
 
 
index 99ad13531c5a6eff4c362a3826cb8e25839f3eb2..aff528d1f8b0bd67168a3d8708253d43a7cad6f4 100644 (file)
@@ -1594,8 +1594,13 @@ namespace TrilinosWrappers
   SparsityPattern::in_local_range (const size_type index) const
   {
     TrilinosWrappers::types::int_type begin, end;
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    begin = graph->RowMap().MinMyGID();
+    end = graph->RowMap().MaxMyGID()+1;
+#else
     begin = graph->RowMap().MinMyGID64();
     end = graph->RowMap().MaxMyGID64()+1;
+#endif
 
     return ((index >= static_cast<size_type>(begin)) &&
             (index < static_cast<size_type>(end)));
index 592815da7b0588b450b404da147c5eff06222a04..18383ff2e8a927a32c53c0b761387d5041d8068b 100644 (file)
@@ -41,6 +41,28 @@ template <typename> class Vector;
 namespace TrilinosWrappers
 {
   class SparseMatrix;
+
+  namespace
+  {
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    // define a helper function that queries the global ID of local ID of 
+    // an Epetra_BlockMap object  by calling either the 32- or 64-bit 
+    // function necessary.
+    int gid(const Epetra_BlockMap &map, int i)
+    {
+      return map.GID(i);
+    }
+#else
+    // define a helper function that queries the global ID of local ID of 
+    // an Epetra_BlockMap object  by calling either the 32- or 64-bit 
+    // function necessary.
+    long long int gid(const Epetra_BlockMap &map, int i)
+    {
+      return map.GID64(i);
+    }
+#endif
+  }
+
   /**
    * Namespace for Trilinos vector classes that work in parallel over
    * MPI. This namespace is restricted to vectors only, whereas matrices
@@ -521,7 +543,7 @@ namespace TrilinosWrappers
       // deal.II might not use doubles, so
       // that a direct access is not possible.
       for (int i=0; i<size; ++i)
-        (*vector)[0][i] = v(parallel_partitioner.GID64(i));
+        (*vector)[0][i] = v(gid(parallel_partitioner,i));
     }
 
 
index 02e2bff5c775dd3f91c791fb0429d5cc6872068f..5414e00d1f47e3c9c2a4bd15bb2c7862b25dbe95 100644 (file)
@@ -52,7 +52,6 @@ namespace TrilinosWrappers
   // forward declaration
   class VectorBase;
 
-
   /**
    * @cond internal
    */
@@ -1470,8 +1469,11 @@ namespace TrilinosWrappers
   VectorBase::size_type
   VectorBase::size () const
   {
-    return (size_type) (vector->Map().MaxAllGID64() + 1 -
-                           vector->Map().MinAllGID64());
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    return (size_type) (vector->Map().MaxAllGID() + 1 - vector->Map().MinAllGID());
+#else
+    return (size_type) (vector->Map().MaxAllGID64() + 1 - vector->Map().MinAllGID64());
+#endif
   }
 
 
@@ -1490,8 +1492,13 @@ namespace TrilinosWrappers
   VectorBase::local_range () const
   {
     TrilinosWrappers::types::int_type begin, end;
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    begin = vector->Map().MinMyGID();
+    end = vector->Map().MaxMyGID()+1;
+#else
     begin = vector->Map().MinMyGID64();
     end = vector->Map().MaxMyGID64()+1;
+#endif
     return std::make_pair (begin, end);
   }
 
index 6203d1f313305f3232ab999ebe49bcf9ffc497d2..2d26d5c0753de7de1cc5eb39484a639bdadc6afb 100644 (file)
@@ -32,6 +32,20 @@ DEAL_II_NAMESPACE_OPEN
 
 namespace TrilinosWrappers
 {
+  namespace
+  {
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    int global_length (const Epetra_MultiVector &vector)
+    {
+      return vector.GlobalLength();
+    }
+#else
+    long long int global_length (const Epetra_MultiVector &vector)
+    {
+      return vector.GlobalLength64();
+    }
+#endif
+  }
 
   PreconditionBase::PreconditionBase()
 #ifdef DEAL_II_WITH_MPI
@@ -591,9 +605,9 @@ namespace TrilinosWrappers
           Assert (n_relevant_rows == my_size,
                   ExcDimensionMismatch(n_relevant_rows, my_size));
         Assert (n_rows ==
-                static_cast<size_type>(distributed_constant_modes.GlobalLength64()),
+                static_cast<size_type>(global_length(distributed_constant_modes)),
                 ExcDimensionMismatch(n_rows,
-                                     distributed_constant_modes.GlobalLength64()));
+                                     global_length(distributed_constant_modes)));
 
         // Reshape null space as a
         // contiguous vector of
index e56078045430837b1a547636c5de9d0ba8f927ac..f2d480d541d60ed2dce0fc648aee4891417f661e 100644 (file)
@@ -34,11 +34,11 @@ namespace TrilinosWrappers
 {
   namespace
   {
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
     // define a helper function that queries the size of an Epetra_Map object
     // by calling either the 32- or 64-bit function necessary, and returns the
     // result in the correct data type so that we can use it in calling other
     // Epetra member functions that are overloaded by index type
-#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
     int n_global_elements (const Epetra_BlockMap &map)
     {
       return map.NumGlobalElements();
@@ -53,7 +53,26 @@ namespace TrilinosWrappers
     {
       return map.MaxMyGID();
     }
+
+    int n_global_cols(const Epetra_CrsGraph &graph)
+    {
+      return graph.NumGlobalCols();
+    }
+
+    int global_column_index(const Epetra_CrsMatrix &matrix, int i)
+    {
+      return matrix.GCID(i);
+    }
+
+    int global_row_index(const Epetra_CrsMatrix &matrix, int i)
+    {
+      return matrix.GRID(i);
+    }
 #else
+    // define a helper function that queries the size of an Epetra_Map object
+    // by calling either the 32- or 64-bit function necessary, and returns the
+    // result in the correct data type so that we can use it in calling other
+    // Epetra member functions that are overloaded by index type
     long long int n_global_elements (const Epetra_BlockMap &map)
     {
       return map.NumGlobalElements64();
@@ -68,6 +87,21 @@ namespace TrilinosWrappers
     {
       return map.MaxMyGID64();
     }
+
+    long long int n_global_cols(const Epetra_CrsGraph &graph)
+    {
+      return graph.NumGlobalCols64();
+    }
+
+    long long int global_column_index(const Epetra_CrsMatrix &matrix, int i)
+    {
+      return matrix.GCID64(i);
+    }
+
+    long long int global_row_index(const Epetra_CrsMatrix &matrix, int i)
+    {
+      return matrix.GRID64(i);
+    }
 #endif
   }
 
@@ -519,7 +553,8 @@ namespace TrilinosWrappers
     graph->OptimizeStorage();
 
     // check whether we got the number of columns right.
-    AssertDimension (sparsity_pattern.n_cols(),static_cast<size_type>(graph->NumGlobalCols64()));
+    AssertDimension (sparsity_pattern.n_cols(),static_cast<size_type>(
+          n_global_cols(*graph)));
 
     // And now finally generate the matrix.
     matrix.reset (new Epetra_FECrsMatrix(Copy, *graph, false));
@@ -1420,7 +1455,8 @@ namespace TrilinosWrappers
           {
             matrix->ExtractMyRowView (i, num_entries, values, indices);
             for (TrilinosWrappers::types::int_type j=0; j<num_entries; ++j)
-              out << "(" << matrix->GRID64(i) << "," << matrix->GCID64(indices[j]) << ") "
+              out << "(" << global_row_index(*matrix,i) << "," 
+                  << global_column_index(*matrix,indices[j]) << ") "
                   << values[j] << std::endl;
           }
       }
index 34066e668a4443bd67e57adf6996dfc04da91a05..5f9925f974c25f4a74de037e44eaa7596c78eb72 100644 (file)
@@ -48,20 +48,25 @@ namespace TrilinosWrappers
       return map.MaxMyGID();
     }
 
-    int n_global_rows(const Epetra_FECrsGraph&graph)
+    int n_global_rows(const Epetra_CrsGraph &graph)
     {
       return graph.NumGlobalRows();
     }
 
-     int n_global_cols(const Epetra_FECrsGraph&graph)
+     int n_global_cols(const Epetra_CrsGraph &graph)
     {
       return graph.NumGlobalCols();
     }
 
-    int n_global_entries(const Epetra_FECrsGraph&graph)
+    int n_global_entries(const Epetra_CrsGraph &graph)
     {
       return graph.NumGlobalEntries();
     }
+
+    int global_row_index(const Epetra_CrsGraph &graph, int i)
+    {
+      return graph.GRID(i);
+    }
  #else
     long long int n_global_elements (const Epetra_BlockMap &map)
     {
@@ -78,19 +83,24 @@ namespace TrilinosWrappers
       return map.MaxMyGID64();
     }
     
-    long long int n_global_rows(const Epetra_FECrsGraph&graph)
+    long long int n_global_rows(const Epetra_CrsGraph &graph)
     {
       return graph.NumGlobalRows64();
     }
 
-    long long int n_global_cols(const Epetra_FECrsGraph&graph)
+    long long int n_global_cols(const Epetra_CrsGraph &graph)
     {
       return graph.NumGlobalCols64();
     }
 
-    long long int n_global_entries(const Epetra_FECrsGraph&graph)
+    long long int n_global_entries(const Epetra_CrsGraph &graph)
     {
-      return graph.NumGlobalEntries();
+      return graph.NumGlobalEntries64();
+    }
+
+    long long int global_row_index(const Epetra_CrsGraph &graph, int i)
+    {
+      return graph.GRID64(i);
     }
 #endif
   }
@@ -315,7 +325,7 @@ namespace TrilinosWrappers
     // release memory before reallocation
     graph.reset ();
     AssertDimension (n_entries_per_row.size(),
-                     static_cast<size_type>(input_row_map.NumGlobalElements64()));
+                     static_cast<size_type>(n_global_elements(input_row_map)));
 
     column_space_map.reset (new Epetra_Map (input_col_map));
     compressed = false;
@@ -383,9 +393,9 @@ namespace TrilinosWrappers
     graph.reset ();
 
     AssertDimension (sp.n_rows(),
-                     static_cast<size_type>(input_row_map.NumGlobalElements64()));
+                     static_cast<size_type>(n_global_elements(input_row_map)));
     AssertDimension (sp.n_cols(),
-                     static_cast<size_type>(input_col_map.NumGlobalElements64()));
+                     static_cast<size_type>(n_global_elements(input_col_map)));
 
     column_space_map.reset (new Epetra_Map (input_col_map));
     compressed = false;
@@ -627,7 +637,7 @@ namespace TrilinosWrappers
     if (graph->Filled() == true)
       n_cols = n_global_cols(*graph);
     else
-      n_cols = column_space_map->NumGlobalElements64();
+      n_cols = n_global_elements(*column_space_map);
 
     return n_cols;
   }
@@ -724,7 +734,7 @@ namespace TrilinosWrappers
           {
             graph->ExtractMyRowView (i, num_entries, indices);
             for (TrilinosWrappers::types::int_type j=0; j<num_entries; ++j)
-              out << "(" << i << "," << indices[graph->GRID64(j)] << ") "
+              out << "(" << i << "," << indices[global_row_index(*graph,j)] << ") "
                   << std::endl;
           }
       }
@@ -750,7 +760,7 @@ namespace TrilinosWrappers
           // j horizontal, gnuplot output is
           // x-y, that is we have to exchange
           // the order of output
-          out << indices[graph->GRID64(static_cast<TrilinosWrappers::types::int_type>(j))]
+          out << indices[global_row_index(*graph,static_cast<int>(j))]
             << " " << -static_cast<TrilinosWrappers::types::int_type>(row)
             << std::endl;
       }
index e58e0abaf3bc60f39f51c564eccf426ab80ce39a..99b65221f7560f8d68b8e584c75e51a7a5e67f0d 100644 (file)
@@ -28,6 +28,61 @@ DEAL_II_NAMESPACE_OPEN
 
 namespace TrilinosWrappers
 {
+  namespace
+  {
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    // define a helper function that queries the size of an Epetra_BlockMap object
+    // by calling either the 32- or 64-bit function necessary, and returns the
+    // result in the correct data type so that we can use it in calling other
+    // Epetra member functions that are overloaded by index type
+    int n_global_elements (const Epetra_BlockMap &map)
+    {
+      return map.NumGlobalElements();
+    }
+    // define a helper function that queries the pointer to internal array
+    // containing list of global IDs assigned to the calling processor
+    // by calling either the 32- or 64-bit function necessary, and returns the
+    // result in the correct data type so that we can use it in calling other
+    // Epetra member functions that are overloaded by index type
+    int* my_global_elements(const Epetra_BlockMap &map)
+    {
+       return map.MyGlobalElements();
+    }
+    // define a helper function that queries the global vector length of an
+    // Epetra_FEVector object  by calling either the 32- or 64-bit 
+    // function necessary.
+    int global_length(const Epetra_FEVector &vector)
+    {
+      return vector.GlobalLength();
+    }
+#else
+    // define a helper function that queries the size of an Epetra_BlockMap object
+    // by calling either the 32- or 64-bit function necessary, and returns the
+    // result in the correct data type so that we can use it in calling other
+    // Epetra member functions that are overloaded by index type
+    long long int n_global_elements (const Epetra_BlockMap &map)
+    {
+      return map.NumGlobalElements64();
+    }
+    // define a helper function that queries the pointer to internal array
+    // containing list of global IDs assigned to the calling processor
+    // by calling either the 32- or 64-bit function necessary, and returns the
+    // result in the correct data type so that we can use it in calling other
+    // Epetra member functions that are overloaded by index type
+    long long int* my_global_elements(const Epetra_BlockMap &map)
+    {
+       return map.MyGlobalElements64();
+    }
+    // define a helper function that queries the global vector length of an
+    // Epetra_FEVector object  by calling either the 32- or 64-bit 
+    // function necessary.
+    long long int global_length(const Epetra_FEVector &vector)
+    {
+      return vector.GlobalLength64();
+    }
+#endif
+  }
+
   namespace MPI
   {
 
@@ -71,9 +126,9 @@ namespace TrilinosWrappers
       :
       VectorBase()
     {
-      AssertThrow (input_map.NumGlobalElements64() == v.vector->Map().NumGlobalElements64(),
-                  ExcDimensionMismatch (input_map.NumGlobalElements64(),
-                                        v.vector->Map().NumGlobalElements64()));
+      AssertThrow (n_global_elements(input_map) == n_global_elements(v.vector->Map()),
+                  ExcDimensionMismatch (n_global_elements(input_map),
+                                        n_global_elements(v.vector->Map())));
 
       last_action = Zero;
 
@@ -95,9 +150,9 @@ namespace TrilinosWrappers
       VectorBase()
     {
       AssertThrow (parallel_partitioner.size() == 
-                   static_cast<size_type>(v.vector->Map().NumGlobalElements64()),
+                   static_cast<size_type>(n_global_elements(v.vector->Map())),
                    ExcDimensionMismatch (parallel_partitioner.size(),
-                                         v.vector->Map().NumGlobalElements64()));
+                                         n_global_elements(v.vector->Map())));
 
       last_action = Zero;
 
@@ -236,7 +291,7 @@ namespace TrilinosWrappers
       for (size_type block=0; block<v.n_blocks(); ++block)
         {
           TrilinosWrappers::types::int_type *glob_elements =
-            v.block(block).vector_partitioner().MyGlobalElements64();
+            my_global_elements(v.block(block).vector_partitioner());
           for (size_type i=0; i<v.block(block).local_size(); ++i)
             global_ids[added_elements++] = glob_elements[i] + block_offset;
           block_offset += v.block(block).size();
@@ -265,9 +320,9 @@ namespace TrilinosWrappers
 
       if (import_data == true)
         {
-          AssertThrow (static_cast<size_type>(actual_vec->GlobalLength64())
+          AssertThrow (static_cast<size_type>(global_length(*actual_vec))
                        == v.size(),
-                       ExcDimensionMismatch (actual_vec->GlobalLength64(),
+                       ExcDimensionMismatch (global_length(*actual_vec),
                                              v.size()));
 
           Epetra_Import data_exchange (vector->Map(), actual_vec->Map());
@@ -387,7 +442,7 @@ namespace TrilinosWrappers
   Vector::Vector (const Epetra_Map &input_map)
   {
     last_action = Zero;
-    Epetra_LocalMap map (input_map.NumGlobalElements64(),
+    Epetra_LocalMap map (n_global_elements(input_map),
                          input_map.IndexBase(),
                          input_map.Comm());
     vector.reset (new Epetra_FEVector(map));
@@ -415,7 +470,7 @@ namespace TrilinosWrappers
   Vector::Vector (const VectorBase &v)
   {
     last_action = Zero;
-    Epetra_LocalMap map (v.vector->Map().NumGlobalElements64(),
+    Epetra_LocalMap map (n_global_elements(v.vector->Map()),
                          v.vector->Map().IndexBase(),
                          v.vector->Map().Comm());
     vector.reset (new Epetra_FEVector(map));
@@ -461,9 +516,9 @@ namespace TrilinosWrappers
   Vector::reinit (const Epetra_Map &input_map,
                   const bool        fast)
   {
-    if (vector->Map().NumGlobalElements64() != input_map.NumGlobalElements64())
+    if (n_global_elements(vector->Map()) != n_global_elements(input_map))
       {
-        Epetra_LocalMap map (input_map.NumGlobalElements64(),
+        Epetra_LocalMap map (n_global_elements(input_map),
                              input_map.IndexBase(),
                              input_map.Comm());
         vector.reset (new Epetra_FEVector (map));
@@ -488,7 +543,7 @@ namespace TrilinosWrappers
                   const MPI_Comm &communicator,
                   const bool      fast)
   {
-    if (vector->Map().NumGlobalElements64() !=
+    if (n_global_elements(vector->Map()) !=
         static_cast<TrilinosWrappers::types::int_type>(partitioning.size()))
       {
         Epetra_LocalMap map (static_cast<TrilinosWrappers::types::int_type>(partitioning.size()),
@@ -532,7 +587,7 @@ namespace TrilinosWrappers
       {
         if (local_range() != v.local_range())
           {
-            Epetra_LocalMap map (v.vector->GlobalLength64(),
+            Epetra_LocalMap map (global_length(*(v.vector)),
                                  v.vector->Map().IndexBase(),
                                  v.vector->Comm());
             vector.reset (new Epetra_FEVector(map));
@@ -587,7 +642,7 @@ namespace TrilinosWrappers
   {
     if (size() != v.size())
       {
-        Epetra_LocalMap map (v.vector->Map().NumGlobalElements64(),
+        Epetra_LocalMap map (n_global_elements(v.vector->Map()),
                              v.vector->Map().IndexBase(),
                              v.vector->Comm());
         vector.reset (new Epetra_FEVector(map));
@@ -604,7 +659,7 @@ namespace TrilinosWrappers
   {
     if (size() != v.size())
       {
-        Epetra_LocalMap map (v.vector->Map().NumGlobalElements64(),
+        Epetra_LocalMap map (n_global_elements(v.vector->Map()),
                              v.vector->Map().IndexBase(),
                              v.vector->Comm());
         vector.reset (new Epetra_FEVector(map));
index c8239f72d2da2161e14eab383531b49148ea44db..c2695901eea87657787dfa8f1306130244d2f692 100644 (file)
@@ -25,6 +25,27 @@ DEAL_II_NAMESPACE_OPEN
 
 namespace TrilinosWrappers
 {
+  namespace
+  {
+#ifndef DEAL_II_USE_LARGE_INDEX_TYPE
+    // define a helper function that queries the global vector length of an
+    // Epetra_FEVector object  by calling either the 32- or 64-bit 
+    // function necessary.
+    int global_length(const Epetra_FEVector &vector)
+    {
+      return vector.GlobalLength();
+    }
+#else
+    // define a helper function that queries the global vector length of an
+    // Epetra_FEVector object  by calling either the 32- or 64-bit 
+    // function necessary.
+    long long int global_length(const Epetra_FEVector &vector)
+    {
+      return vector.GlobalLength64();
+    }
+#endif
+  }
+
   namespace internal
   {
     VectorReference::operator TrilinosScalar () const
@@ -350,7 +371,7 @@ namespace TrilinosWrappers
   void
   VectorBase::print (const char *format) const
   {
-    Assert (vector->GlobalLength64()!=0, ExcEmptyObject());
+    Assert (global_length(*vector)!=0, ExcEmptyObject());
 
     for (size_type j=0; j<size(); ++j)
       {

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.