protected function gradient(Matrix $p, Matrix $y, Matrix $distances) : Matrix
    {
        $q = $distances->square()
            ->divide($this->degrees)
            ->add(1.)
            ->pow((1. + $this->degrees) / -2.);

        $qSigma = $q->sum()->multiply(2.);

        $q = $q->divide($qSigma)
            ->clipLower(EPSILON);

        $pqd = $p->subtract($q)
            ->multiply($distances);

        $c = 2. * (1. + $this->degrees) / $this->degrees;

        $gradient = [];

        foreach ($pqd->asVectors() as $i => $row) {
            $yHat = $y->rowAsVector($i)
                ->subtract($y);
            
            $gradient[] = $row->matmul($yHat)
                ->multiply($c)
                ->row(0);
        }

        return Matrix::quick($gradient);
    }