/home/kueuepay/public_html/vendor/markbaker/matrix/classes/src/Matrix.php
<?php

/**
 *
 * Class for the management of Matrices
 *
 * @copyright  Copyright (c) 2018 Mark Baker (https://github.com/MarkBaker/PHPMatrix)
 * @license    https://opensource.org/licenses/MIT    MIT
 */

namespace Matrix;

use Generator;
use Matrix\Decomposition\LU;
use Matrix\Decomposition\QR;

/**
 * Matrix object.
 *
 * @package Matrix
 *
 * @property-read int $rows The number of rows in the matrix
 * @property-read int $columns The number of columns in the matrix
 * @method Matrix antidiagonal()
 * @method Matrix adjoint()
 * @method Matrix cofactors()
 * @method float determinant()
 * @method Matrix diagonal()
 * @method Matrix identity()
 * @method Matrix inverse()
 * @method Matrix minors()
 * @method float trace()
 * @method Matrix transpose()
 * @method Matrix add(...$matrices)
 * @method Matrix subtract(...$matrices)
 * @method Matrix multiply(...$matrices)
 * @method Matrix divideby(...$matrices)
 * @method Matrix divideinto(...$matrices)
 * @method Matrix directsum(...$matrices)
 */
class Matrix
{
    protected $rows;
    protected $columns;
    protected $grid = [];

    /*
     * Create a new Matrix object from an array of values
     *
     * @param array $grid
     */
    final public function __construct(array $grid)
    {
        $this->buildFromArray(array_values($grid));
    }

    /*
     * Create a new Matrix object from an array of values
     *
     * @param array $grid
     */
    protected function buildFromArray(array $grid): void
    {
        $this->rows = count($grid);
        $columns = array_reduce(
            $grid,
            function ($carry, $value) {
                return max($carry, is_array($value) ? count($value) : 1);
            }
        );
        $this->columns = $columns;

        array_walk(
            $grid,
            function (&$value) use ($columns) {
                if (!is_array($value)) {
                    $value = [$value];
                }
                $value = array_pad(array_values($value), $columns, null);
            }
        );

        $this->grid = $grid;
    }

    /**
     * Validate that a row number is a positive integer
     *
     * @param int $row
     * @return int
     * @throws Exception
     */
    public static function validateRow(int $row): int
    {
        if ((!is_numeric($row)) || (intval($row) < 1)) {
            throw new Exception('Invalid Row');
        }

        return (int)$row;
    }

    /**
     * Validate that a column number is a positive integer
     *
     * @param int $column
     * @return int
     * @throws Exception
     */
    public static function validateColumn(int $column): int
    {
        if ((!is_numeric($column)) || (intval($column) < 1)) {
            throw new Exception('Invalid Column');
        }

        return (int)$column;
    }

    /**
     * Validate that a row number falls within the set of rows for this matrix
     *
     * @param int $row
     * @return int
     * @throws Exception
     */
    protected function validateRowInRange(int $row): int
    {
        $row = static::validateRow($row);
        if ($row > $this->rows) {
            throw new Exception('Requested Row exceeds matrix size');
        }

        return $row;
    }

    /**
     * Validate that a column number falls within the set of columns for this matrix
     *
     * @param int $column
     * @return int
     * @throws Exception
     */
    protected function validateColumnInRange(int $column): int
    {
        $column = static::validateColumn($column);
        if ($column > $this->columns) {
            throw new Exception('Requested Column exceeds matrix size');
        }

        return $column;
    }

    /**
     * Return a new matrix as a subset of rows from this matrix, starting at row number $row, and $rowCount rows
     * A $rowCount value of 0 will return all rows of the matrix from $row
     * A negative $rowCount value will return rows until that many rows from the end of the matrix
     *
     * Note that row numbers start from 1, not from 0
     *
     * @param int $row
     * @param int $rowCount
     * @return static
     * @throws Exception
     */
    public function getRows(int $row, int $rowCount = 1): Matrix
    {
        $row = $this->validateRowInRange($row);
        if ($rowCount === 0) {
            $rowCount = $this->rows - $row + 1;
        }

        return new static(array_slice($this->grid, $row - 1, (int)$rowCount));
    }

    /**
     * Return a new matrix as a subset of columns from this matrix, starting at column number $column, and $columnCount columns
     * A $columnCount value of 0 will return all columns of the matrix from $column
     * A negative $columnCount value will return columns until that many columns from the end of the matrix
     *
     * Note that column numbers start from 1, not from 0
     *
     * @param int $column
     * @param int $columnCount
     * @return Matrix
     * @throws Exception
     */
    public function getColumns(int $column, int $columnCount = 1): Matrix
    {
        $column = $this->validateColumnInRange($column);
        if ($columnCount < 1) {
            $columnCount = $this->columns + $columnCount - $column + 1;
        }

        $grid = [];
        for ($i = $column - 1; $i < $column + $columnCount - 1; ++$i) {
            $grid[] = array_column($this->grid, $i);
        }

        return (new static($grid))->transpose();
    }

    /**
     * Return a new matrix as a subset of rows from this matrix, dropping rows starting at row number $row,
     *     and $rowCount rows
     * A negative $rowCount value will drop rows until that many rows from the end of the matrix
     * A $rowCount value of 0 will remove all rows of the matrix from $row
     *
     * Note that row numbers start from 1, not from 0
     *
     * @param int $row
     * @param int $rowCount
     * @return static
     * @throws Exception
     */
    public function dropRows(int $row, int $rowCount = 1): Matrix
    {
        $this->validateRowInRange($row);
        if ($rowCount === 0) {
            $rowCount = $this->rows - $row + 1;
        }

        $grid = $this->grid;
        array_splice($grid, $row - 1, (int)$rowCount);

        return new static($grid);
    }

    /**
     * Return a new matrix as a subset of columns from this matrix, dropping columns starting at column number $column,
     *     and $columnCount columns
     * A negative $columnCount value will drop columns until that many columns from the end of the matrix
     * A $columnCount value of 0 will remove all columns of the matrix from $column
     *
     * Note that column numbers start from 1, not from 0
     *
     * @param int $column
     * @param int $columnCount
     * @return static
     * @throws Exception
     */
    public function dropColumns(int $column, int $columnCount = 1): Matrix
    {
        $this->validateColumnInRange($column);
        if ($columnCount < 1) {
            $columnCount = $this->columns + $columnCount - $column + 1;
        }

        $grid = $this->grid;
        array_walk(
            $grid,
            function (&$row) use ($column, $columnCount) {
                array_splice($row, $column - 1, (int)$columnCount);
            }
        );

        return new static($grid);
    }

    /**
     * Return a value from this matrix, from the "cell" identified by the row and column numbers
     * Note that row and column numbers start from 1, not from 0
     *
     * @param int $row
     * @param int $column
     * @return mixed
     * @throws Exception
     */
    public function getValue(int $row, int $column)
    {
        $row = $this->validateRowInRange($row);
        $column = $this->validateColumnInRange($column);

        return $this->grid[$row - 1][$column - 1];
    }

    /**
     * Returns a Generator that will yield each row of the matrix in turn as a vector matrix
     *     or the value of each cell if the matrix is a column vector
     *
     * @return Generator|Matrix[]|mixed[]
     */
    public function rows(): Generator
    {
        foreach ($this->grid as $i => $row) {
            yield $i + 1 => ($this->columns == 1)
                ? $row[0]
                : new static([$row]);
        }
    }

    /**
     * Returns a Generator that will yield each column of the matrix in turn as a vector matrix
     *     or the value of each cell if the matrix is a row vector
     *
     * @return Generator|Matrix[]|mixed[]
     */
    public function columns(): Generator
    {
        for ($i = 0; $i < $this->columns; ++$i) {
            yield $i + 1 => ($this->rows == 1)
                ? $this->grid[0][$i]
                : new static(array_column($this->grid, $i));
        }
    }

    /**
     * Identify if the row and column dimensions of this matrix are equal,
     *     i.e. if it is a "square" matrix
     *
     * @return bool
     */
    public function isSquare(): bool
    {
        return $this->rows === $this->columns;
    }

    /**
     * Identify if this matrix is a vector
     *     i.e. if it comprises only a single row or a single column
     *
     * @return bool
     */
    public function isVector(): bool
    {
        return $this->rows === 1 || $this->columns === 1;
    }

    /**
     * Return the matrix as a 2-dimensional array
     *
     * @return array
     */
    public function toArray(): array
    {
        return $this->grid;
    }

    /**
     * Solve A*X = B.
     *
     * @param Matrix $B Right hand side
     *
     * @throws Exception
     *
     * @return Matrix ... Solution if A is square, least squares solution otherwise
     */
    public function solve(Matrix $B): Matrix
    {
        if ($this->columns === $this->rows) {
            return (new LU($this))->solve($B);
        }

        return (new QR($this))->solve($B);
    }

    protected static $getters = [
        'rows',
        'columns',
    ];

    /**
     * Access specific properties as read-only (no setters)
     *
     * @param string $propertyName
     * @return mixed
     * @throws Exception
     */
    public function __get(string $propertyName)
    {
        $propertyName = strtolower($propertyName);

        // Test for function calls
        if (in_array($propertyName, self::$getters)) {
            return $this->$propertyName;
        }

        throw new Exception('Property does not exist');
    }

    protected static $functions = [
        'adjoint',
        'antidiagonal',
        'cofactors',
        'determinant',
        'diagonal',
        'identity',
        'inverse',
        'minors',
        'trace',
        'transpose',
    ];

    protected static $operations = [
        'add',
        'subtract',
        'multiply',
        'divideby',
        'divideinto',
        'directsum',
    ];

    /**
     * Returns the result of the function call or operation
     *
     * @param string $functionName
     * @param mixed[] $arguments
     * @return Matrix|float
     * @throws Exception
     */
    public function __call(string $functionName, $arguments)
    {
        $functionName = strtolower(str_replace('_', '', $functionName));

        // Test for function calls
        if (in_array($functionName, self::$functions, true)) {
            return Functions::$functionName($this, ...$arguments);
        }
        // Test for operation calls
        if (in_array($functionName, self::$operations, true)) {
            return Operations::$functionName($this, ...$arguments);
        }
        throw new Exception('Function or Operation does not exist');
    }
}
About
top

About NFC Pay: Our Story and Mission

NFC Pay was founded with a vision to transform the way people handle transactions. Our journey is defined by a commitment to innovation, security, and convenience. We strive to deliver seamless, user-friendly payment solutions that make everyday transactions effortless and secure. Our mission is to empower you to pay with ease and confidence, anytime, anywhere.

  • Simplifying Payments, One Tap at a Time.
  • Reinventing Your Wallet for Modern Convenience.
  • Smart Payments for a Effortless Lifestyle.
  • Experience the Ease of Tap and Pay.
  • Innovative Solutions for Your Daily Transactions.

Frequently Asked Questions About NFC Pay

Here are answers to some common questions about NFC Pay. We aim to provide clear and concise information to help you understand how our platform works and how it can benefit you. If you have any further inquiries, please don’t hesitate to contact our support team.

faq-img

How do I register for NFC Pay?

Download the app and sign up using your email or phone number, then complete the verification process.

Is my payment information secure?

Yes, we use advanced encryption and security protocols to protect your payment details.

Can I add multiple cards to my NFC Pay wallet?

Absolutely, you can link multiple debit or credit cards to your wallet.

How do I transfer money to another user?

Go to the transfer section, select the recipient, enter the amount, and authorize the transfer.

What should I do if I forget my PIN?

Use the “Forgot PIN” feature in the app to reset it following the provided instructions.

How can I activate my merchant account?

Sign up for a merchant account through the app and follow the setup instructions to start accepting payments.

Can I track my payment status?

Yes, you can view and track your payment status in the account dashboard