View Javadoc

1   /*
2   
3       dsh-matrix  long-addressable bit and typed object matrix implementations.
4       Copyright (c) 2004-2013 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package org.dishevelled.matrix.impl;
25  
26  import java.util.Iterator;
27  import java.util.NoSuchElementException;
28  
29  import org.dishevelled.matrix.BitMatrix1D;
30  import org.dishevelled.matrix.Matrix1D;
31  
32  import org.dishevelled.functor.UnaryFunction;
33  import org.dishevelled.functor.UnaryProcedure;
34  import org.dishevelled.functor.UnaryPredicate;
35  import org.dishevelled.functor.BinaryFunction;
36  import org.dishevelled.functor.BinaryProcedure;
37  import org.dishevelled.functor.BinaryPredicate;
38  
39  /**
40   * Abstract implementation of Matrix1D.
41   *
42   * @param <E> type of this abstract 1D matrix
43   * @author  Michael Heuer
44   */
45  abstract class AbstractMatrix1D<E>
46      implements Matrix1D<E>
47  {
48      /** Size. */
49      protected long size;
50  
51      /** Index of the first element. */
52      protected long zero;
53  
54      /** Number of indices between any two elements. */
55      protected long stride;
56  
57      /** True if this instance is a view. */
58      protected boolean isView;
59  
60  
61      /**
62       * Protected no-arg constructor, to support serialization.
63       */
64      protected AbstractMatrix1D()
65      {
66          // empty
67      }
68  
69      /**
70       * Create a new abstract 1D matrix with the specified size.
71       *
72       * @param size size, must be <code>&gt;= 0</code>
73       * @throws IllegalArgumentException if <code>size</code> is negative
74       */
75      protected AbstractMatrix1D(final long size)
76      {
77          if (size < 0)
78          {
79              throw new IllegalArgumentException(size + " < 0");
80          }
81  
82          this.size = size;
83          this.zero = 0L;
84          this.stride = 1L;
85          this.isView = false;
86      }
87  
88      /**
89       * Create a new abstract 1D matrix with the specified parameters.
90       *
91       * @param size size, must be <code>&gt;= 0</code>
92       * @param zero index of the first element
93       * @param stride number of indices between any two elements
94       * @param isView true if this instance is a view
95       */
96      protected AbstractMatrix1D(final long size,
97                                       final long zero,
98                                       final long stride,
99                                       final boolean isView)
100     {
101         if (size < 0)
102         {
103             throw new IllegalArgumentException(size + " < 0");
104         }
105 
106         this.size = size;
107         this.zero = zero;
108         this.stride = stride;
109         this.isView = isView;
110     }
111 
112 
113     /** {@inheritDoc} */
114     public long size()
115     {
116         return size;
117     }
118 
119     /** {@inheritDoc} */
120     public long cardinality()
121     {
122         long cardinality = 0;
123         for (E e : this)
124         {
125             if (e != null)
126             {
127                 cardinality++;
128             }
129         }
130         return cardinality;
131     }
132 
133     /** {@inheritDoc} */
134     public boolean isEmpty()
135     {
136         return (0 == cardinality());
137     }
138 
139     /** {@inheritDoc} */
140     public void clear()
141     {
142         forEach(new BinaryProcedure<Long, E>()
143             {
144                 public void run(final Long index, final E e)
145                 {
146                     if (e != null)
147                     {
148                         set(index, null);
149                     }
150                 }
151             });
152     }
153 
154     /** {@inheritDoc} */
155     public Iterator<E> iterator()
156     {
157         return new ObjectMatrix1DIterator();
158     }
159 
160     /** {@inheritDoc} */
161     public E get(final long index)
162     {
163         if (index < 0)
164         {
165             throw new IndexOutOfBoundsException(index + " < 0");
166         }
167         if (index >= size)
168         {
169             throw new IndexOutOfBoundsException(index + " >= " + size);
170         }
171 
172         return getQuick(index);
173     }
174 
175     /** {@inheritDoc} */
176     public void set(final long index, final E e)
177     {
178         if (index < 0)
179         {
180             throw new IndexOutOfBoundsException(index + " < 0");
181         }
182         if (index >= size)
183         {
184             throw new IndexOutOfBoundsException(index + " > " + size);
185         }
186 
187         setQuick(index, e);
188     }
189 
190     /** {@inheritDoc} */
191     public void setQuick(final long index, final E e)
192     {
193         throw new UnsupportedOperationException();
194     }
195 
196     /** {@inheritDoc} */
197     public Matrix1D<E> assign(final E e)
198     {
199         forEach(new BinaryProcedure<Long, E>()
200             {
201                 public void run(final Long index, final E ignore)
202                 {
203                     setQuick(index, e);
204                 }
205             });
206 
207         return this;
208     }
209 
210     /** {@inheritDoc} */
211     public Matrix1D<E> assign(final UnaryFunction<E, E> function)
212     {
213         if (function == null)
214         {
215             throw new IllegalArgumentException("function must not be null");
216         }
217 
218         forEach(new BinaryProcedure<Long, E>()
219             {
220                 public void run(final Long index, final E e)
221                 {
222                     setQuick(index, function.evaluate(e));
223                 }
224             });
225 
226         return this;
227     }
228 
229     /** {@inheritDoc} */
230     public Matrix1D<E> assign(final Matrix1D<? extends E> other)
231     {
232         if (other == null)
233         {
234             throw new IllegalArgumentException("other must not be null");
235         }
236         if (!(size == other.size()))
237         {
238             throw new IllegalArgumentException("this and other must be the same size");
239         }
240 
241         forEach(new BinaryProcedure<Long, E>()
242             {
243                 public void run(final Long index, final E ignore)
244                 {
245                     E e = other.getQuick(index);
246                     setQuick(index, e);
247                 }
248             });
249 
250         return this;
251     }
252 
253     /** {@inheritDoc} */
254     public Matrix1D<E> assign(final Matrix1D<? extends E> other,
255                                     final BinaryFunction<E, E, E> function)
256     {
257         if (other == null)
258         {
259             throw new IllegalArgumentException("other must not be null");
260         }
261         if (size != other.size())
262         {
263             throw new IllegalArgumentException("this and other must be the same size");
264         }
265         if (function == null)
266         {
267             throw new IllegalArgumentException("function must not be null");
268         }
269 
270         forEach(new BinaryProcedure<Long, E>()
271             {
272                 public void run(final Long index, final E e)
273                 {
274                     E result = function.evaluate(e, other.getQuick(index));
275                     setQuick(index, result);
276                 }
277             });
278 
279         return this;
280     }
281 
282     /** {@inheritDoc} */
283     public E aggregate(final BinaryFunction<E, E, E> aggr, final UnaryFunction<E, E> function)
284     {
285         if (aggr == null)
286         {
287             throw new IllegalArgumentException("aggr must not be null");
288         }
289         if (function == null)
290         {
291             throw new IllegalArgumentException("function must not be null");
292         }
293         if (size == 0)
294         {
295             return null;
296         }
297         long last = (size - 1L);
298         E a = function.evaluate(getQuick(last));
299         for (long index = last; --index >= 0;)
300         {
301             a = aggr.evaluate(a, function.evaluate(getQuick(index)));
302         }
303         return a;
304     }
305 
306     /** {@inheritDoc} */
307     public E aggregate(final Matrix1D<? extends E> other,
308                        final BinaryFunction<E, E, E> aggr,
309                        final BinaryFunction<E, E, E> function)
310     {
311         if (other == null)
312         {
313             throw new IllegalArgumentException("other must not be null");
314         }
315         if (!(size == other.size()))
316         {
317             throw new IllegalArgumentException("this and other must be the same size");
318         }
319         if (aggr == null)
320         {
321             throw new IllegalArgumentException("aggr must not be null");
322         }
323         if (function == null)
324         {
325             throw new IllegalArgumentException("function must not be null");
326         }
327 
328         if (size == 0)
329         {
330             return null;
331         }
332 
333         long last = (size - 1L);
334         E a = function.evaluate(getQuick(last), other.getQuick(last));
335         for (long index = last; --index >= 0;)
336         {
337             a = aggr.evaluate(a, function.evaluate(getQuick(index), other.getQuick(index)));
338         }
339         return a;
340     }
341 
342     /**
343      * Create a new view.
344      *
345      * @return a new view
346      */
347     protected AbstractMatrix1D<E> view()
348     {
349         try
350         {
351             AbstractMatrix1D<E> m = (AbstractMatrix1D<E>) clone();
352             return m;
353         }
354         catch (CloneNotSupportedException e)
355         {
356             throw new RuntimeException(e);
357         }
358     }
359 
360     /**
361      * Self-modifying version of <code>viewFlip()</code>.
362      *
363      * @return modified version of <code>this</code>
364      */
365     protected AbstractMatrix1D<E> vFlip()
366     {
367         if (size > 0)
368         {
369             zero += (size - 1) * stride;
370             stride = -stride;
371             isView = true;
372         }
373 
374         return this;
375     }
376 
377     /** {@inheritDoc} */
378     public Matrix1D<E> viewFlip()
379     {
380         return view().vFlip();
381     }
382 
383     /**
384      * Self-modifying version of <code>viewPart(long, long)</code>.
385      *
386      * @param index index
387      * @param width width
388      * @return modified version of <code>this</code>
389      */
390     protected AbstractMatrix1D<E> vPart(final long index, final long width)
391     {
392         if (size > 0)
393         {
394             zero += (stride * index);
395             size = width;
396             isView = true;
397         }
398 
399         return this;
400     }
401 
402     /** {@inheritDoc} */
403     public Matrix1D<E> viewPart(final long index, final long width)
404     {
405         return view().vPart(index, width);
406     }
407 
408     /** {@inheritDoc} */
409     public Matrix1D<E> viewSelection(final long[] indices)
410     {
411         return null;
412     }
413 
414     /** {@inheritDoc} */
415     public Matrix1D<E> viewSelection(final UnaryPredicate<E> predicate)
416     {
417         return null;
418     }
419 
420     /** {@inheritDoc} */
421     public Matrix1D<E> viewSelection(final BitMatrix1D mask)
422     {
423         return null;
424     }
425 
426     /**
427      * Self-modifying version of <code>viewStrides(long)</code>.
428      *
429      * @param stride stride
430      * @return modified version of <code>this</code>
431      */
432     protected AbstractMatrix1D<E> vStrides(final long stride)
433     {
434         this.stride *= stride;
435 
436         if (size != 0)
437         {
438             size = ((size - 1) / stride) + 1L;
439         }
440         isView = true;
441 
442         return this;
443     }
444 
445     /** {@inheritDoc} */
446     public Matrix1D<E> viewStrides(final long stride)
447     {
448         return view().vStrides(stride);
449     }
450 
451     /** {@inheritDoc} */
452     public void forEach(final UnaryProcedure<? super E> procedure)
453     {
454         if (procedure == null)
455         {
456             throw new IllegalArgumentException("procedure must not be null");
457         }
458 
459         for (long index = 0; index < size; index++)
460         {
461             E e = getQuick(index);
462             procedure.run(e);
463         }
464     }
465 
466     /** {@inheritDoc} */
467     public void forEach(final UnaryPredicate<? super E> predicate,
468                         final UnaryProcedure<? super E> procedure)
469     {
470         if (predicate == null)
471         {
472             throw new IllegalArgumentException("predicate must not be null");
473         }
474         if (procedure == null)
475         {
476             throw new IllegalArgumentException("procedure must not be null");
477         }
478 
479         for (long index = 0; index < size; index++)
480         {
481             E e = getQuick(index);
482             if (predicate.test(e))
483             {
484                 procedure.run(e);
485             }
486         }
487     }
488 
489     /** {@inheritDoc} */
490     public void forEachNonNull(final UnaryProcedure<? super E> procedure)
491     {
492         forEach(new UnaryPredicate<E>()
493                 {
494                     public boolean test(final E e)
495                     {
496                         return (e != null);
497                     }
498                 }, procedure);
499     }
500 
501     /** {@inheritDoc} */
502     public void forEach(final BinaryProcedure<Long, ? super E> procedure)
503     {
504         if (procedure == null)
505         {
506             throw new IllegalArgumentException("procedure must not be null");
507         }
508 
509         for (long index = 0; index < size; index++)
510         {
511             E e = getQuick(index);
512             procedure.run(index, e);
513         }
514     }
515 
516     /** {@inheritDoc} */
517     public void forEach(final BinaryPredicate<Long, ? super E> predicate,
518                         final BinaryProcedure<Long, ? super E> procedure)
519     {
520         if (predicate == null)
521         {
522             throw new IllegalArgumentException("predicate must not be null");
523         }
524         if (procedure == null)
525         {
526             throw new IllegalArgumentException("procedure must not be null");
527         }
528 
529         for (long index = 0; index < size; index++)
530         {
531             E e = getQuick(index);
532             if (predicate.test(index, e))
533             {
534                 procedure.run(index, e);
535             }
536         }
537     }
538 
539     /**
540      * Return the index of the first element.
541      *
542      * @return the index of the first element
543      */
544     protected long zero()
545     {
546         return zero;
547     }
548 
549     /**
550      * Return the number of indices between any two elements.
551      *
552      * @return the number of indices between any two elements
553      */
554     protected long stride()
555     {
556         return stride;
557     }
558 
559     /**
560      * Return true if this instance is a view.
561      *
562      * @return true if this instance is a view
563      */
564     protected boolean isView()
565     {
566         return isView;
567     }
568 
569     /** {@inheritDoc} */
570     public String toString()
571     {
572         final StringBuffer sb = new StringBuffer();
573         sb.append(size);
574         sb.append(" matrix\n");
575 
576         forEach(new BinaryProcedure<Long, E>()
577                 {
578                     public void run(final Long index, final E e)
579                     {
580                         sb.append((e == null) ? "null" : e.toString());
581                         if (index != (size() - 1))
582                         {
583                             sb.append(" ");
584                         }
585                     }
586                 });
587 
588         return sb.toString();
589     }
590 
591     /**
592      * Matrix1D iterator.
593      */
594     private class ObjectMatrix1DIterator
595         implements Iterator<E>
596     {
597         /** Index. */
598         private long index = 0L;
599 
600 
601         /** {@inheritDoc} */
602         public boolean hasNext()
603         {
604             return (index < size);
605         }
606 
607         /** {@inheritDoc} */
608         public E next()
609         {
610             if (index < size)
611             {
612                 E e = getQuick(index);
613                 index++;
614                 return e;
615             }
616             else
617             {
618                 throw new NoSuchElementException("index=" + index);
619             }
620         }
621 
622         /** {@inheritDoc} */
623         public void remove()
624         {
625             throw new UnsupportedOperationException();
626         }
627     }
628 }