// Copyright (C) 2017  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#ifndef DLIB_DNN_CuSOLVER_H_
#define DLIB_DNN_CuSOLVER_H_
#ifdef DLIB_USE_CUDA
#include "tensor.h"
#include "cuda_errors.h"
#include "cuda_data_ptr.h"
#include "../noncopyable.h"
namespace dlib
{
    namespace cuda 
    {
    // -----------------------------------------------------------------------------------
        class inv : noncopyable
        {
            /*!
                WHAT THIS OBJECT REPRESENTS
                    This is a functor for doing matrix inversion on the GPU.  The only
                    reason it's an object is to avoid the reallocation of some GPU memory
                    blocks if you want to do a bunch of matrix inversions in a row.
            !*/
        public:
            inv() = default;
            ~inv();
            void operator() (
                const tensor& m,
                resizable_tensor& out
            );
            /*!
                requires
                    - m.size() == m.num_samples()*m.num_samples()
                      (i.e. mat(m) must be a square matrix)
                ensures
                    - out == inv(mat(m));
            !*/
            int get_last_status(
            );
            /*!
                ensures
                    - returns 0 if the last matrix inversion was successful and != 0
                      otherwise.
            !*/
        private:
            void sync_if_needed();
            bool did_work_lately = false;
            resizable_tensor m;
            cuda_data_ptr<float> workspace;
            cuda_data_ptr<int> Ipiv;
            cuda_data_ptr<int> info;
        };
    // ------------------------------------------------------------------------------------
    }  
}
#endif // DLIB_USE_CUDA
#endif // DLIB_DNN_CuSOLVER_H_