/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix2x2D;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix2x2F;

import java.nio.ByteBuffer;

/**
 *
A storage matrix.

 *
Storage component type: {@code double}

 *
Storage component count: {@code 2x2}

 */

public final class MatrixByteBuffered2x2s64
  extends TensorByteBufferedFloating64
  implements MatrixByteBuffered2x2Type
{
  private MatrixByteBuffered2x2s64(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static MatrixByteBuffered2x2s64 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new MatrixByteBuffered2x2s64(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 2 * 2;
  }

  @Override
  public double r0c0()
  {
    return this.getValue(ColumnMajor.index2x2(0, 0));
  }

  @Override
  public double r0c1()
  {
    return this.getValue(ColumnMajor.index2x2(0, 1));
  }

  @Override
  public double r1c0()
  {
    return this.getValue(ColumnMajor.index2x2(1, 0));
  }

  @Override
  public double r1c1()
  {
    return this.getValue(ColumnMajor.index2x2(1, 1));
  }

  @Override
  public void setMatrix2x2D(final Matrix2x2D m)
  {
    this.putValue(ColumnMajor.index2x2(0, 0), m.r0c0());
    this.putValue(ColumnMajor.index2x2(0, 1), m.r0c1());

    this.putValue(ColumnMajor.index2x2(1, 0), m.r1c0());
    this.putValue(ColumnMajor.index2x2(1, 1), m.r1c1());
  }

  @Override
  public void setMatrix2x2F(final Matrix2x2F m)
  {
    this.putValue(ColumnMajor.index2x2(0, 0), (double) m.r0c0());
    this.putValue(ColumnMajor.index2x2(0, 1), (double) m.r0c1());

    this.putValue(ColumnMajor.index2x2(1, 0), (double) m.r1c0());
    this.putValue(ColumnMajor.index2x2(1, 1), (double) m.r1c1());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code int}

 *
Storage component count: {@code 2}

 */

public final class VectorByteBufferedIntegral2s32
  extends TensorByteBufferedIntegral32
  implements VectorByteBufferedIntegral2Type
{
  private VectorByteBufferedIntegral2s32(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static VectorByteBufferedIntegral2s32 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new VectorByteBufferedIntegral2s32(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 2;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code double}

 *
Storage component count: {@code 3}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedFloating3s64<T>
  extends TensorByteBufferedFloating64
  implements PVectorByteBufferedFloating3Type<T>
{
  private PVectorByteBufferedFloating3s64(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedFloating3s64<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedFloating3s64<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 3;
  }

  @Override
  public double x()
  {
    return this.getValue(0);
  }

  @Override
  public double y()
  {
    return this.getValue(1);
  }

  @Override
  public double z()
  {
    return this.getValue(2);
  }

  @Override
  public void setX(final double x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final double y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final double z)
  {
    this.putValue(2, z);
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.parameterized.vectors.PVector2D;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A vector generator.
 *
 * @param <T>
 */

public final class PVector2DGenerator<T> implements Generator<PVector2D<T>>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public PVector2DGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator that
   * produces values in the range {@code [-(2 ^ 16), 2 ^ 16]}.
   *
   * @param <T> A phantom type parameter
   *
   * @return A generator
   */

  public static <T> Generator<PVector2D<T>> createSmall()
  {
    return new PVector2DGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_SMALL_DOUBLE_LOWER,
      GeneratorConstants.BOUND_SMALL_DOUBLE_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @param <T> A phantom type parameter
   *
   * @return A generator
   */

  public static <T> Generator<PVector2D<T>> create()
  {
    return new PVector2DGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_DOUBLE_LOWER,
      GeneratorConstants.BOUND_LARGE_DOUBLE_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that
   * produces values in the range {@code [-1, 1]}.
   *
   * @param <T> A phantom type parameter
   *
   * @return A generator
   */

  public static <T> Generator<PVector2D<T>> createNormal()
  {
    return new PVector2DGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_DOUBLE_LOWER,
      GeneratorConstants.BOUND_NORMAL_DOUBLE_UPPER
    ));
  }

  @Override
  public PVector2D<T> next()
  {
    return PVector2D.of(
      this.gen.next().doubleValue(),
      this.gen.next().doubleValue());
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.parameterized.matrices.PMatrix4x4F;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A matrix generator.
 *
 * @param <A> A phantom type parameter (possibly representing a source
 *            coordinate system)
 * @param <B> A phantom type parameter (possibly representing a target
 *            coordinate system)
 */

public final class PMatrix4x4FGenerator<A, B> implements Generator<PMatrix4x4F<A, B>>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public PMatrix4x4FGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @param <A> A phantom type parameter (possibly representing a source
   *            coordinate system)
   * @param <B> A phantom type parameter (possibly representing a target
   *            coordinate system)
   *
   * @return A generator
   */

  public static <A, B> Generator<PMatrix4x4F<A, B>> create()
  {
    return new PMatrix4x4FGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_FLOAT_LOWER,
      GeneratorConstants.BOUND_LARGE_FLOAT_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that only
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @param <A> A phantom type parameter (possibly representing a source
   *            coordinate system)
   * @param <B> A phantom type parameter (possibly representing a target
   *            coordinate system)
   *
   * @return A generator
   */

  public static <A, B> Generator<PMatrix4x4F<A, B>> createNormal()
  {
    return new PMatrix4x4FGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_FLOAT_LOWER,
      GeneratorConstants.BOUND_NORMAL_FLOAT_UPPER
    ));
  }

  @Override
  public PMatrix4x4F<A, B> next()
  {
    return PMatrix4x4F.of(
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code int}

 *
Storage component count: {@code 4}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedIntegral4s32<T>
  extends TensorByteBufferedIntegral32
  implements PVectorByteBufferedIntegral4Type<T>
{
  private PVectorByteBufferedIntegral4s32(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedIntegral4s32<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedIntegral4s32<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 4;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public long z()
  {
    return this.getValue(2);
  }

  @Override
  public long w()
  {
    return this.getValue(3);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final long z)
  {
    this.putValue(2, z);
  }

  @Override
  public void setW(final long w)
  {
    this.putValue(3, w);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code short}

 *
Storage component count: {@code 4}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedIntegral4s16<T>
  extends TensorByteBufferedIntegral16
  implements PVectorByteBufferedIntegral4Type<T>
{
  private PVectorByteBufferedIntegral4s16(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedIntegral4s16<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedIntegral4s16<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 4;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public long z()
  {
    return this.getValue(2);
  }

  @Override
  public long w()
  {
    return this.getValue(3);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final long z)
  {
    this.putValue(2, z);
  }

  @Override
  public void setW(final long w)
  {
    this.putValue(3, w);
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.core.unparameterized.matrices;

import com.io7m.jtensors.core.determinants.Determinants;
import com.io7m.junreachable.UnreachableCodeException;

final class MatrixDOps
{
  private MatrixDOps()
  {
    throw new UnreachableCodeException();
  }

  static double zero()
  {
    return 0.0;
  }

  static double one()
  {
    return 1.0;
  }

  static double sine(
    final double a)
  {
    return StrictMath.sin(a);
  }

  static double cosine(
    final double a)
  {
    return StrictMath.cos(a);
  }

  static double determinant3x3(
    final double r0c0,
    final double r0c1,
    final double r0c2,
    final double r1c0,
    final double r1c1,
    final double r1c2,
    final double r2c0,
    final double r2c1,
    final double r2c2)
  {
    return Determinants.determinant3x3(
      r0c0, r0c1, r0c2,
      r1c0, r1c1, r1c2,
      r2c0, r2c1, r2c2);
  }

  // CHECKSTYLE:OFF
  static double determinant4x4(
    final double r0c0,
    final double r0c1,
    final double r0c2,
    final double r0c3,
    final double r1c0,
    final double r1c1,
    final double r1c2,
    final double r1c3,
    final double r2c0,
    final double r2c1,
    final double r2c2,
    final double r2c3,
    final double r3c0,
    final double r3c1,
    final double r3c2,
    final double r3c3)
  // CHECKSTYLE:ON
  {
    return Determinants.determinant4x4(
      r0c0, r0c1, r0c2, r0c3,
      r1c0, r1c1, r1c2, r1c3,
      r2c0, r2c1, r2c2, r2c3,
      r3c0, r3c1, r3c2, r3c3);
  }

  static double determinant2x2(
    final double r0c0,
    final double r0c1,
    final double r1c0,
    final double r1c1)
  {
    return Determinants.determinant2x2(
      r0c0, r0c1,
      r1c0, r1c1);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code long}

 *
Storage component count: {@code 2}

 */

public final class VectorByteBufferedIntegral2s64
  extends TensorByteBufferedIntegral64
  implements VectorByteBufferedIntegral2Type
{
  private VectorByteBufferedIntegral2s64(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static VectorByteBufferedIntegral2s64 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new VectorByteBufferedIntegral2s64(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 2;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix2x2D;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix2x2F;

import java.nio.ByteBuffer;

/**
 *
A storage matrix.

 *
Storage component type: {@code float}

 *
Storage component count: {@code 2x2}

 */

public final class MatrixByteBuffered2x2s32
  extends TensorByteBufferedFloating32
  implements MatrixByteBuffered2x2Type
{
  private MatrixByteBuffered2x2s32(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static MatrixByteBuffered2x2s32 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new MatrixByteBuffered2x2s32(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 2 * 2;
  }

  @Override
  public double r0c0()
  {
    return this.getValue(ColumnMajor.index2x2(0, 0));
  }

  @Override
  public double r0c1()
  {
    return this.getValue(ColumnMajor.index2x2(0, 1));
  }

  @Override
  public double r1c0()
  {
    return this.getValue(ColumnMajor.index2x2(1, 0));
  }

  @Override
  public double r1c1()
  {
    return this.getValue(ColumnMajor.index2x2(1, 1));
  }

  @Override
  public void setMatrix2x2D(final Matrix2x2D m)
  {
    this.putValue(ColumnMajor.index2x2(0, 0), m.r0c0());
    this.putValue(ColumnMajor.index2x2(0, 1), m.r0c1());

    this.putValue(ColumnMajor.index2x2(1, 0), m.r1c0());
    this.putValue(ColumnMajor.index2x2(1, 1), m.r1c1());
  }

  @Override
  public void setMatrix2x2F(final Matrix2x2F m)
  {
    this.putValue(ColumnMajor.index2x2(0, 0), (double) m.r0c0());
    this.putValue(ColumnMajor.index2x2(0, 1), (double) m.r0c1());

    this.putValue(ColumnMajor.index2x2(1, 0), (double) m.r1c0());
    this.putValue(ColumnMajor.index2x2(1, 1), (double) m.r1c1());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code double}

 *
Storage component count: {@code 2}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedFloating2s64<T>
  extends TensorByteBufferedFloating64
  implements PVectorByteBufferedFloating2Type<T>
{
  private PVectorByteBufferedFloating2s64(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedFloating2s64<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedFloating2s64<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 2;
  }

  @Override
  public double x()
  {
    return this.getValue(0);
  }

  @Override
  public double y()
  {
    return this.getValue(1);
  }

  @Override
  public void setX(final double x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final double y)
  {
    this.putValue(1, y);
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix3x3F;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A matrix generator.
 */

public final class Matrix3x3FGenerator implements Generator<Matrix3x3F>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public Matrix3x3FGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @return A generator
   */

  public static Generator<Matrix3x3F> create()
  {
    return new Matrix3x3FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_FLOAT_LOWER,
      GeneratorConstants.BOUND_LARGE_FLOAT_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that only
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @return A generator
   */

  public static Generator<Matrix3x3F> createNormal()
  {
    return new Matrix3x3FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_FLOAT_LOWER,
      GeneratorConstants.BOUND_NORMAL_FLOAT_UPPER
    ));
  }

  @Override
  public Matrix3x3F next()
  {
    return Matrix3x3F.of(
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code short}

 *
Storage component count: {@code 4}

 */

public final class VectorByteBufferedIntegral4s16
  extends TensorByteBufferedIntegral16
  implements VectorByteBufferedIntegral4Type
{
  private VectorByteBufferedIntegral4s16(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static VectorByteBufferedIntegral4s16 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new VectorByteBufferedIntegral4s16(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 4;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public long z()
  {
    return this.getValue(2);
  }

  @Override
  public long w()
  {
    return this.getValue(3);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final long z)
  {
    this.putValue(2, z);
  }

  @Override
  public void setW(final long w)
  {
    this.putValue(3, w);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code int}

 *
Storage component count: {@code 3}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedIntegral3s32<T>
  extends TensorByteBufferedIntegral32
  implements PVectorByteBufferedIntegral3Type<T>
{
  private PVectorByteBufferedIntegral3s32(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedIntegral3s32<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedIntegral3s32<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 3;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public long z()
  {
    return this.getValue(2);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final long z)
  {
    this.putValue(2, z);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code binary16}

 *
Storage component count: {@code 4}

 */

public final class VectorByteBufferedFloating4s16
  extends TensorByteBufferedFloating16
  implements VectorByteBufferedFloating4Type
{
  private VectorByteBufferedFloating4s16(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static VectorByteBufferedFloating4s16 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new VectorByteBufferedFloating4s16(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 4;
  }

  @Override
  public double x()
  {
    return this.getValue(0);
  }

  @Override
  public double y()
  {
    return this.getValue(1);
  }

  @Override
  public double z()
  {
    return this.getValue(2);
  }

  @Override
  public double w()
  {
    return this.getValue(3);
  }

  @Override
  public void setX(final double x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final double y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final double z)
  {
    this.putValue(2, z);
  }

  @Override
  public void setW(final double w)
  {
    this.putValue(3, w);
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.parameterized.matrices.PMatrix3x3F;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A matrix generator.
 *
 * @param <A> A phantom type parameter (possibly representing a source
 *            coordinate system)
 * @param <B> A phantom type parameter (possibly representing a target
 *            coordinate system)
 */

public final class PMatrix3x3FGenerator<A, B> implements Generator<PMatrix3x3F<A, B>>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public PMatrix3x3FGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @param <A> A phantom type parameter (possibly representing a source
   *            coordinate system)
   * @param <B> A phantom type parameter (possibly representing a target
   *            coordinate system)
   *
   * @return A generator
   */

  public static <A, B> Generator<PMatrix3x3F<A, B>> create()
  {
    return new PMatrix3x3FGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_FLOAT_LOWER,
      GeneratorConstants.BOUND_LARGE_FLOAT_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that only
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @param <A> A phantom type parameter (possibly representing a source
   *            coordinate system)
   * @param <B> A phantom type parameter (possibly representing a target
   *            coordinate system)
   *
   * @return A generator
   */

  public static <A, B> Generator<PMatrix3x3F<A, B>> createNormal()
  {
    return new PMatrix3x3FGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_FLOAT_LOWER,
      GeneratorConstants.BOUND_NORMAL_FLOAT_UPPER
    ));
  }

  @Override
  public PMatrix3x3F<A, B> next()
  {
    return PMatrix3x3F.of(
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue());
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix2x2D;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A matrix generator.
 */

public final class Matrix2x2DGenerator implements Generator<Matrix2x2D>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public Matrix2x2DGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @return A generator
   */

  public static Generator<Matrix2x2D> create()
  {
    return new Matrix2x2DGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_DOUBLE_LOWER,
      GeneratorConstants.BOUND_LARGE_DOUBLE_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that only
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @return A generator
   */

  public static Generator<Matrix2x2D> createNormal()
  {
    return new Matrix2x2DGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_DOUBLE_LOWER,
      GeneratorConstants.BOUND_NORMAL_DOUBLE_UPPER
    ));
  }

  @Override
  public Matrix2x2D next()
  {
    return Matrix2x2D.of(
      this.gen.next().doubleValue(),
      this.gen.next().doubleValue(),
      this.gen.next().doubleValue(),
      this.gen.next().doubleValue());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix4x4D;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix4x4F;

import java.nio.ByteBuffer;

/**
 *
A storage matrix.

 *
Storage component type: {@code double}

 *
Storage component count: {@code 4x4}

 */

public final class MatrixByteBuffered4x4s64
  extends TensorByteBufferedFloating64
  implements MatrixByteBuffered4x4Type
{
  private MatrixByteBuffered4x4s64(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static MatrixByteBuffered4x4s64 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new MatrixByteBuffered4x4s64(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 4 * 4;
  }

  @Override
  public double r0c0()
  {
    return this.getValue(ColumnMajor.index4x4(0, 0));
  }

  @Override
  public double r0c1()
  {
    return this.getValue(ColumnMajor.index4x4(0, 1));
  }

  @Override
  public double r0c2()
  {
    return this.getValue(ColumnMajor.index4x4(0, 2));
  }

  @Override
  public double r0c3()
  {
    return this.getValue(ColumnMajor.index4x4(0, 3));
  }

  @Override
  public double r1c0()
  {
    return this.getValue(ColumnMajor.index4x4(1, 0));
  }

  @Override
  public double r1c1()
  {
    return this.getValue(ColumnMajor.index4x4(1, 1));
  }

  @Override
  public double r1c2()
  {
    return this.getValue(ColumnMajor.index4x4(1, 2));
  }

  @Override
  public double r1c3()
  {
    return this.getValue(ColumnMajor.index4x4(1, 3));
  }

  @Override
  public double r2c0()
  {
    return this.getValue(ColumnMajor.index4x4(2, 0));
  }

  @Override
  public double r2c1()
  {
    return this.getValue(ColumnMajor.index4x4(2, 1));
  }

  @Override
  public double r2c2()
  {
    return this.getValue(ColumnMajor.index4x4(2, 2));
  }

  @Override
  public double r2c3()
  {
    return this.getValue(ColumnMajor.index4x4(2, 3));
  }

  @Override
  public double r3c0()
  {
    return this.getValue(ColumnMajor.index4x4(3, 0));
  }

  @Override
  public double r3c1()
  {
    return this.getValue(ColumnMajor.index4x4(3, 1));
  }

  @Override
  public double r3c2()
  {
    return this.getValue(ColumnMajor.index4x4(3, 2));
  }

  @Override
  public double r3c3()
  {
    return this.getValue(ColumnMajor.index4x4(3, 3));
  }

  @Override
  public void setMatrix4x4D(final Matrix4x4D m)
  {
    this.putValue(ColumnMajor.index4x4(0, 0), m.r0c0());
    this.putValue(ColumnMajor.index4x4(0, 1), m.r0c1());
    this.putValue(ColumnMajor.index4x4(0, 2), m.r0c2());
    this.putValue(ColumnMajor.index4x4(0, 3), m.r0c3());

    this.putValue(ColumnMajor.index4x4(1, 0), m.r1c0());
    this.putValue(ColumnMajor.index4x4(1, 1), m.r1c1());
    this.putValue(ColumnMajor.index4x4(1, 2), m.r1c2());
    this.putValue(ColumnMajor.index4x4(1, 3), m.r1c3());

    this.putValue(ColumnMajor.index4x4(2, 0), m.r2c0());
    this.putValue(ColumnMajor.index4x4(2, 1), m.r2c1());
    this.putValue(ColumnMajor.index4x4(2, 2), m.r2c2());
    this.putValue(ColumnMajor.index4x4(2, 3), m.r2c3());

    this.putValue(ColumnMajor.index4x4(3, 0), m.r3c0());
    this.putValue(ColumnMajor.index4x4(3, 1), m.r3c1());
    this.putValue(ColumnMajor.index4x4(3, 2), m.r3c2());
    this.putValue(ColumnMajor.index4x4(3, 3), m.r3c3());
  }

  @Override
  public void setMatrix4x4F(final Matrix4x4F m)
  {
    this.putValue(ColumnMajor.index4x4(0, 0), (double) m.r0c0());
    this.putValue(ColumnMajor.index4x4(0, 1), (double) m.r0c1());
    this.putValue(ColumnMajor.index4x4(0, 2), (double) m.r0c2());
    this.putValue(ColumnMajor.index4x4(0, 3), (double) m.r0c3());

    this.putValue(ColumnMajor.index4x4(1, 0), (double) m.r1c0());
    this.putValue(ColumnMajor.index4x4(1, 1), (double) m.r1c1());
    this.putValue(ColumnMajor.index4x4(1, 2), (double) m.r1c2());
    this.putValue(ColumnMajor.index4x4(1, 3), (double) m.r1c3());

    this.putValue(ColumnMajor.index4x4(2, 0), (double) m.r2c0());
    this.putValue(ColumnMajor.index4x4(2, 1), (double) m.r2c1());
    this.putValue(ColumnMajor.index4x4(2, 2), (double) m.r2c2());
    this.putValue(ColumnMajor.index4x4(2, 3), (double) m.r2c3());

    this.putValue(ColumnMajor.index4x4(3, 0), (double) m.r3c0());
    this.putValue(ColumnMajor.index4x4(3, 1), (double) m.r3c1());
    this.putValue(ColumnMajor.index4x4(3, 2), (double) m.r3c2());
    this.putValue(ColumnMajor.index4x4(3, 3), (double) m.r3c3());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code short}

 *
Storage component count: {@code 3}

 */

public final class VectorByteBufferedIntegral3s16
  extends TensorByteBufferedIntegral16
  implements VectorByteBufferedIntegral3Type
{
  private VectorByteBufferedIntegral3s16(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static VectorByteBufferedIntegral3s16 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new VectorByteBufferedIntegral3s16(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 3;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public long z()
  {
    return this.getValue(2);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final long z)
  {
    this.putValue(2, z);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code byte}

 *
Storage component count: {@code 2}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedIntegral2s8<T>
  extends TensorByteBufferedIntegral8
  implements PVectorByteBufferedIntegral2Type<T>
{
  private PVectorByteBufferedIntegral2s8(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedIntegral2s8<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedIntegral2s8<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 2;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code double}

 *
Storage component count: {@code 4}

 */

public final class VectorByteBufferedFloating4s64
  extends TensorByteBufferedFloating64
  implements VectorByteBufferedFloating4Type
{
  private VectorByteBufferedFloating4s64(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static VectorByteBufferedFloating4s64 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new VectorByteBufferedFloating4s64(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 4;
  }

  @Override
  public double x()
  {
    return this.getValue(0);
  }

  @Override
  public double y()
  {
    return this.getValue(1);
  }

  @Override
  public double z()
  {
    return this.getValue(2);
  }

  @Override
  public double w()
  {
    return this.getValue(3);
  }

  @Override
  public void setX(final double x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final double y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final double z)
  {
    this.putValue(2, z);
  }

  @Override
  public void setW(final double w)
  {
    this.putValue(3, w);
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.orthonormalization;

import com.io7m.jtensors.core.unparameterized.vectors.Vector3D;
import com.io7m.jtensors.core.unparameterized.vectors.Vector4D;
import com.io7m.jtensors.core.unparameterized.vectors.Vectors3D;
import com.io7m.jtensors.core.unparameterized.vectors.Vectors4D;
import com.io7m.junreachable.UnreachableCodeException;

/**
 * Functions to orthonormalize sets of vectors.
 */

public final class Orthonormalization
{
  private Orthonormalization()
  {
    throw new UnreachableCodeException();
  }

  /**
   * Orthonormalize the given vectors.
   *
   * @param v0 Vector 0
   * @param v1 Vector 1
   * @param v2 Vector 2
   *
   * @return The set of vectors, orthonormalized
   */

  public static Orthonormalized3D orthonormalize3D(
    final Vector3D v0,
    final Vector3D v1,
    final Vector3D v2)
  {
    final Vector3D rv0 = Vectors3D.normalize(v0);
    final Vector3D rv1;
    final Vector3D rv2;

    {
      final double v0_dot_v1 = Vectors3D.dotProduct(rv0, v1);
      final Vector3D v0_s = Vectors3D.scale(rv0, v0_dot_v1);
      rv1 = Vectors3D.normalize(Vectors3D.subtract(v1, v0_s));
    }

    {
      final double v1_dot_v2 = Vectors3D.dotProduct(rv1, v2);
      final double v0_dot_v2 = Vectors3D.dotProduct(rv0, v2);

      final Vector3D v0_s = Vectors3D.scale(rv0, v0_dot_v2);
      final Vector3D v2_s = Vectors3D.scale(rv1, v1_dot_v2);
      final Vector3D vs = Vectors3D.add(v0_s, v2_s);
      rv2 = Vectors3D.normalize(Vectors3D.subtract(v2, vs));
    }

    return Orthonormalized3D.of(rv0, rv1, rv2);
  }

  /**
   * Orthonormalize the given vectors.
   *
   * @param v0 Vector 0
   * @param v1 Vector 1
   * @param v2 Vector 2
   *
   * @return The set of vectors, orthonormalized
   */

  public static Orthonormalized4D orthonormalize4D(
    final Vector4D v0,
    final Vector4D v1,
    final Vector4D v2)
  {
    final Vector4D rv0 = Vectors4D.normalize(v0);
    final Vector4D rv1;
    final Vector4D rv2;

    {
      final double v0_dot_v1 = Vectors4D.dotProduct(rv0, v1);
      final Vector4D v0_s = Vectors4D.scale(rv0, v0_dot_v1);
      rv1 = Vectors4D.normalize(Vectors4D.subtract(v1, v0_s));
    }

    {
      final double v1_dot_v2 = Vectors4D.dotProduct(rv1, v2);
      final double v0_dot_v2 = Vectors4D.dotProduct(rv0, v2);

      final Vector4D v0_s = Vectors4D.scale(rv0, v0_dot_v2);
      final Vector4D v2_s = Vectors4D.scale(rv1, v1_dot_v2);
      final Vector4D vs = Vectors4D.add(v0_s, v2_s);
      rv2 = Vectors4D.normalize(Vectors4D.subtract(v2, vs));
    }

    return Orthonormalized4D.of(rv0, rv1, rv2);
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.unparameterized.vectors.Vector2F;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A vector generator.
 */

public final class Vector2FGenerator implements Generator<Vector2F>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public Vector2FGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @return A generator
   */

  public static Generator<Vector2F> create()
  {
    return new Vector2FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_FLOAT_LOWER,
      GeneratorConstants.BOUND_LARGE_FLOAT_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that
   * produces values in the range {@code [-65536.0, 65536.0]}.
   *
   * @return A generator
   */

  public static Generator<Vector2F> createSmall()
  {
    return new Vector2FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_SMALL_FLOAT_LOWER,
      GeneratorConstants.BOUND_SMALL_FLOAT_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @return A generator
   */

  public static Generator<Vector2F> createNormal()
  {
    return new Vector2FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_FLOAT_LOWER,
      GeneratorConstants.BOUND_NORMAL_FLOAT_UPPER
    ));
  }

  @Override
  public Vector2F next()
  {
    return Vector2F.of(
      this.gen.next().floatValue(),
      this.gen.next().floatValue());
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.security.SecureRandom;
import java.util.Objects;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix4x4F;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A matrix generator.
 */

public final class Matrix4x4FGenerator implements Generator<Matrix4x4F>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public Matrix4x4FGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @return A generator
   */

  public static Generator<Matrix4x4F> create()
  {
    return new Matrix4x4FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_FLOAT_LOWER,
      GeneratorConstants.BOUND_LARGE_FLOAT_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that only
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @return A generator
   */

  public static Generator<Matrix4x4F> createNormal()
  {
    return new Matrix4x4FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_FLOAT_LOWER,
      GeneratorConstants.BOUND_NORMAL_FLOAT_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that only
   * produces orthogonal matrices.
   *
   * @return A generator
   */

  public static Generator<Matrix4x4F> createOrthogonal()
  {
    return () -> {
      final SecureRandom rng = new SecureRandom();

      final float r0c0 = 1.0F;
      final float r0c1 = 0.0F;
      final float r0c2 = 0.0F;
      final float r0c3 = rng.nextFloat();

      final float r1c0 = 0.0F;
      final float r1c1 = 1.0F;
      final float r1c2 = 0.0F;
      final float r1c3 = rng.nextFloat();

      final float r2c0 = 0.0F;
      final float r2c1 = 0.0F;
      final float r2c2 = 1.0F;
      final float r2c3 = rng.nextFloat();

      final float r3c0 = 0.0F;
      final float r3c1 = 0.0F;
      final float r3c2 = 0.0F;
      final float r3c3 = 1.0F;

      return Matrix4x4F.of(
        r0c0, r0c1, r0c2, r0c3,
        r1c0, r1c1, r1c2, r1c3,
        r2c0, r2c1, r2c2, r2c3,
        r3c0, r3c1, r3c2, r3c3);
    };
  }

  @Override
  public Matrix4x4F next()
  {
    return Matrix4x4F.of(
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix3x3D;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix3x3F;

import java.nio.ByteBuffer;

/**
 *
A storage matrix.

 *
Storage component type: {@code binary16}

 *
Storage component count: {@code 3x3}

 */

public final class MatrixByteBuffered3x3s16
  extends TensorByteBufferedFloating32
  implements MatrixByteBuffered3x3Type
{
  private MatrixByteBuffered3x3s16(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static MatrixByteBuffered3x3s16 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new MatrixByteBuffered3x3s16(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 3 * 3;
  }

  @Override
  public double r0c0()
  {
    return this.getValue(ColumnMajor.index3x3(0, 0));
  }

  @Override
  public double r0c1()
  {
    return this.getValue(ColumnMajor.index3x3(0, 1));
  }

  @Override
  public double r0c2()
  {
    return this.getValue(ColumnMajor.index3x3(0, 2));
  }

  @Override
  public double r1c0()
  {
    return this.getValue(ColumnMajor.index3x3(1, 0));
  }

  @Override
  public double r1c1()
  {
    return this.getValue(ColumnMajor.index3x3(1, 1));
  }

  @Override
  public double r1c2()
  {
    return this.getValue(ColumnMajor.index3x3(1, 2));
  }

  @Override
  public double r2c0()
  {
    return this.getValue(ColumnMajor.index3x3(2, 0));
  }

  @Override
  public double r2c1()
  {
    return this.getValue(ColumnMajor.index3x3(2, 1));
  }

  @Override
  public double r2c2()
  {
    return this.getValue(ColumnMajor.index3x3(2, 2));
  }

  @Override
  public void setMatrix3x3D(final Matrix3x3D m)
  {
    this.putValue(ColumnMajor.index3x3(0, 0), m.r0c0());
    this.putValue(ColumnMajor.index3x3(0, 1), m.r0c1());
    this.putValue(ColumnMajor.index3x3(0, 2), m.r0c2());

    this.putValue(ColumnMajor.index3x3(1, 0), m.r1c0());
    this.putValue(ColumnMajor.index3x3(1, 1), m.r1c1());
    this.putValue(ColumnMajor.index3x3(1, 2), m.r1c2());

    this.putValue(ColumnMajor.index3x3(2, 0), m.r2c0());
    this.putValue(ColumnMajor.index3x3(2, 1), m.r2c1());
    this.putValue(ColumnMajor.index3x3(2, 2), m.r2c2());
  }

  @Override
  public void setMatrix3x3F(final Matrix3x3F m)
  {
    this.putValue(ColumnMajor.index3x3(0, 0), (double) m.r0c0());
    this.putValue(ColumnMajor.index3x3(0, 1), (double) m.r0c1());
    this.putValue(ColumnMajor.index3x3(0, 2), (double) m.r0c2());

    this.putValue(ColumnMajor.index3x3(1, 0), (double) m.r1c0());
    this.putValue(ColumnMajor.index3x3(1, 1), (double) m.r1c1());
    this.putValue(ColumnMajor.index3x3(1, 2), (double) m.r1c2());

    this.putValue(ColumnMajor.index3x3(2, 0), (double) m.r2c0());
    this.putValue(ColumnMajor.index3x3(2, 1), (double) m.r2c1());
    this.putValue(ColumnMajor.index3x3(2, 2), (double) m.r2c2());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code float}

 *
Storage component count: {@code 2}

 */

public final class VectorByteBufferedFloating2s32
  extends TensorByteBufferedFloating32
  implements VectorByteBufferedFloating2Type
{
  private VectorByteBufferedFloating2s32(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static VectorByteBufferedFloating2s32 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new VectorByteBufferedFloating2s32(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 2;
  }

  @Override
  public double x()
  {
    return this.getValue(0);
  }

  @Override
  public double y()
  {
    return this.getValue(1);
  }

  @Override
  public void setX(final double x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final double y)
  {
    this.putValue(1, y);
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix2x2F;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A matrix generator.
 */

public final class Matrix2x2FGenerator implements Generator<Matrix2x2F>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public Matrix2x2FGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @return A generator
   */

  public static Generator<Matrix2x2F> create()
  {
    return new Matrix2x2FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_FLOAT_LOWER,
      GeneratorConstants.BOUND_LARGE_FLOAT_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that only
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @return A generator
   */

  public static Generator<Matrix2x2F> createNormal()
  {
    return new Matrix2x2FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_FLOAT_LOWER,
      GeneratorConstants.BOUND_NORMAL_FLOAT_UPPER
    ));
  }

  @Override
  public Matrix2x2F next()
  {
    return Matrix2x2F.of(
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code binary16}

 *
Storage component count: {@code 4}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedFloating4s16<T>
  extends TensorByteBufferedFloating16
  implements PVectorByteBufferedFloating4Type<T>
{
  private PVectorByteBufferedFloating4s16(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedFloating4s16<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedFloating4s16<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 4;
  }

  @Override
  public double x()
  {
    return this.getValue(0);
  }

  @Override
  public double y()
  {
    return this.getValue(1);
  }

  @Override
  public double z()
  {
    return this.getValue(2);
  }

  @Override
  public double w()
  {
    return this.getValue(3);
  }

  @Override
  public void setX(final double x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final double y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final double z)
  {
    this.putValue(2, z);
  }

  @Override
  public void setW(final double w)
  {
    this.putValue(3, w);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code short}

 *
Storage component count: {@code 3}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedIntegral3s16<T>
  extends TensorByteBufferedIntegral16
  implements PVectorByteBufferedIntegral3Type<T>
{
  private PVectorByteBufferedIntegral3s16(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedIntegral3s16<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedIntegral3s16<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 3;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public long z()
  {
    return this.getValue(2);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final long z)
  {
    this.putValue(2, z);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code float}

 *
Storage component count: {@code 2}

 *
 * @param <T> A phantom type parameter
 */

public final class PVectorByteBufferedFloating2s32<T>
  extends TensorByteBufferedFloating32
  implements PVectorByteBufferedFloating2Type<T>
{
  private PVectorByteBufferedFloating2s32(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param <T>    A phantom type parameter
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static <T> PVectorByteBufferedFloating2s32<T> createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new PVectorByteBufferedFloating2s32<>(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 2;
  }

  @Override
  public double x()
  {
    return this.getValue(0);
  }

  @Override
  public double y()
  {
    return this.getValue(1);
  }

  @Override
  public void setX(final double x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final double y)
  {
    this.putValue(1, y);
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;

import java.nio.ByteBuffer;

/**
 *
A storage vector.

 *
Storage component type: {@code int}

 *
Storage component count: {@code 4}

 */

public final class VectorByteBufferedIntegral4s32
  extends TensorByteBufferedIntegral32
  implements VectorByteBufferedIntegral4Type
{
  private VectorByteBufferedIntegral4s32(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static VectorByteBufferedIntegral4s32 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new VectorByteBufferedIntegral4s32(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 4;
  }

  @Override
  public long x()
  {
    return this.getValue(0);
  }

  @Override
  public long y()
  {
    return this.getValue(1);
  }

  @Override
  public long z()
  {
    return this.getValue(2);
  }

  @Override
  public long w()
  {
    return this.getValue(3);
  }

  @Override
  public void setX(final long x)
  {
    this.putValue(0, x);
  }

  @Override
  public void setY(final long y)
  {
    this.putValue(1, y);
  }

  @Override
  public void setZ(final long z)
  {
    this.putValue(2, z);
  }

  @Override
  public void setW(final long w)
  {
    this.putValue(3, w);
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.quaternions.Quaternion4F;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A quaternion generator.
 */

public final class Quaternion4FGenerator implements Generator<Quaternion4F>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public Quaternion4FGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator that
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @param <T> A phantom type parameter
   *
   * @return A generator
   */

  public static <T> Generator<Quaternion4F> create()
  {
    return new Quaternion4FGenerator(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_FLOAT_LOWER,
      GeneratorConstants.BOUND_NORMAL_FLOAT_UPPER
    ));
  }

  @Override
  public Quaternion4F next()
  {
    return Quaternion4F.of(
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue(),
      this.gen.next().floatValue());
  }
}


/*
 * Copyright © 2017 <code@io7m.com> http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.generators;

import java.util.Objects;
import com.io7m.jtensors.core.parameterized.vectors.PVector3D;
import net.java.quickcheck.Generator;
import net.java.quickcheck.generator.PrimitiveGenerators;

/**
 * A vector generator.
 *
 * @param <T>
 */

public final class PVector3DGenerator<T> implements Generator<PVector3D<T>>
{
  private final Generator<Double> gen;

  /**
   * Construct a generator.
   *
   * @param in_gen A component generator
   */

  public PVector3DGenerator(
    final Generator<Double> in_gen)
  {
    this.gen = Objects.requireNonNull(in_gen, "Generator");
  }

  /**
   * Create a generator initialized with a default component generator that
   * produces values in the range {@code [-(2 ^ 16), 2 ^ 16]}.
   *
   * @param <T> A phantom type parameter
   *
   * @return A generator
   */

  public static <T> Generator<PVector3D<T>> createSmall()
  {
    return new PVector3DGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_SMALL_DOUBLE_LOWER,
      GeneratorConstants.BOUND_SMALL_DOUBLE_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator.
   *
   * @param <T> A phantom type parameter
   *
   * @return A generator
   */

  public static <T> Generator<PVector3D<T>> create()
  {
    return new PVector3DGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_LARGE_DOUBLE_LOWER,
      GeneratorConstants.BOUND_LARGE_DOUBLE_UPPER
    ));
  }

  /**
   * Create a generator initialized with a default component generator that
   * produces values in the range {@code [-1.0, 1.0]}.
   *
   * @param <T> A phantom type parameter
   *
   * @return A generator
   */

  public static <T> Generator<PVector3D<T>> createNormal()
  {
    return new PVector3DGenerator<>(PrimitiveGenerators.doubles(
      GeneratorConstants.BOUND_NORMAL_DOUBLE_LOWER,
      GeneratorConstants.BOUND_NORMAL_DOUBLE_UPPER
    ));
  }

  @Override
  public PVector3D<T> next()
  {
    return PVector3D.of(
      this.gen.next().doubleValue(),
      this.gen.next().doubleValue(),
      this.gen.next().doubleValue());
  }
}


/*
 * Copyright © 2017  http://io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors.storage.bytebuffered;

import com.io7m.mutable.numbers.core.MutableLongType;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix3x3D;
import com.io7m.jtensors.core.unparameterized.matrices.Matrix3x3F;

import java.nio.ByteBuffer;

/**
 *
A storage matrix.

 *
Storage component type: {@code float}

 *
Storage component count: {@code 3x3}

 */

public final class MatrixByteBuffered3x3s32
  extends TensorByteBufferedFloating32
  implements MatrixByteBuffered3x3Type
{
  private MatrixByteBuffered3x3s32(
    final ByteBuffer in_buffer,
    final MutableLongType in_base,
    final int in_offset)
  {
    super(in_buffer, in_base, in_offset);
  }

  /**
   *
Return a new vector that is backed by the given byte buffer {@code
   * b}

   *
   *
The data for the instance will be taken from the data at the current
   * value of {@code base.get() + offset}, each time a field is requested or
   * set.

   *
   *
No initialization of the data is performed.

   *
   * @param b      The byte buffer
   * @param base   The base address
   * @param offset A constant offset
   *
   * @return A new buffered vector
   */

  public static MatrixByteBuffered3x3s32 createWithBase(
    final ByteBuffer b,
    final MutableLongType base,
    final int offset)
  {
    return new MatrixByteBuffered3x3s32(b, base, offset);
  }

  @Override
  protected int componentCount()
  {
    return 3 * 3;
  }

  @Override
  public double r0c0()
  {
    return this.getValue(ColumnMajor.index3x3(0, 0));
  }

  @Override
  public double r0c1()
  {
    return this.getValue(ColumnMajor.index3x3(0, 1));
  }

  @Override
  public double r0c2()
  {
    return this.getValue(ColumnMajor.index3x3(0, 2));
  }

  @Override
  public double r1c0()
  {
    return this.getValue(ColumnMajor.index3x3(1, 0));
  }

  @Override
  public double r1c1()
  {
    return this.getValue(ColumnMajor.index3x3(1, 1));
  }

  @Override
  public double r1c2()
  {
    return this.getValue(ColumnMajor.index3x3(1, 2));
  }

  @Override
  public double r2c0()
  {
    return this.getValue(ColumnMajor.index3x3(2, 0));
  }

  @Override
  public double r2c1()
  {
    return this.getValue(ColumnMajor.index3x3(2, 1));
  }

  @Override
  public double r2c2()
  {
    return this.getValue(ColumnMajor.index3x3(2, 2));
  }

  @Override
  public void setMatrix3x3D(final Matrix3x3D m)
  {
    this.putValue(ColumnMajor.index3x3(0, 0), m.r0c0());
    this.putValue(ColumnMajor.index3x3(0, 1), m.r0c1());
    this.putValue(ColumnMajor.index3x3(0, 2), m.r0c2());

    this.putValue(ColumnMajor.index3x3(1, 0), m.r1c0());
    this.putValue(ColumnMajor.index3x3(1, 1), m.r1c1());
    this.putValue(ColumnMajor.index3x3(1, 2), m.r1c2());

    this.putValue(ColumnMajor.index3x3(2, 0), m.r2c0());
    this.putValue(ColumnMajor.index3x3(2, 1), m.r2c1());
    this.putValue(ColumnMajor.index3x3(2, 2), m.r2c2());
  }

  @Override
  public void setMatrix3x3F(final Matrix3x3F m)
  {
    this.putValue(ColumnMajor.index3x3(0, 0), (double) m.r0c0());
    this.putValue(ColumnMajor.index3x3(0, 1), (double) m.r0c1());
    this.putValue(ColumnMajor.index3x3(0, 2), (double) m.r0c2());

    this.putValue(ColumnMajor.index3x3(1, 0), (double) m.r1c0());
    this.putValue(ColumnMajor.index3x3(1, 1), (double) m.r1c1());
    this.putValue(ColumnMajor.index3x3(1, 2), (double) m.r1c2());

    this.putValue(ColumnMajor.index3x3(2, 0), (double) m.r2c0());
    this.putValue(ColumnMajor.index3x3(2, 1), (double) m.r2c1());
    this.putValue(ColumnMajor.index3x3(2, 2), (double) m.r2c2());
  }
}