You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: nntest.m
    path of file: ./repos/Pedestrian_Alignment/matlab/xtest/suite
    
    the code of the file until where you have to start completion: classdef nntest < matlab.unittest.TestCase
  properties (ClassSetupParameter)
    device = {'cpu', 'gpu'}
    dataType = {'single', 'double'}
  end

  properties
    currentDevice
    currentDataType
    randn
    rand
    zeros
    ones
    toDevice
    toDataType
    range = 128
  end

  methods (TestClassSetup)
    function generators(test, device, dataType)
      test.currentDevice = device ;
      test.currentDataType = dataType ;
      switch dataType
        case 'single'
          test.toDataType = @(x) single(x) ;
        case 'double'
          test.toDataType = @(x) double(x) ;
      end
      switch device
        case 'gpu'
          gpuDevice ;
          test.randn = @(varargin) test.range * gpuArray.randn
    
function generators(test, device, dataType)
      test.currentDevice = device ;
      test.currentDataType = dataType ;
      switch dataType
        case 'single'
          test.toDataType = @(x) single(x) ;
        case 'double'
          test.toDataType = @(x) double(x) ;
      end
      switch device
        case 'gpu'
          gpuDevice ;
          test.randn = @(varargin) test.range * gpuArray.randn(varargin{:},dataType) ;
          test.rand = @(varargin) test.range * gpuArray.rand(varargin{:},dataType) ;
          test.zeros = @(varargin) gpuArray.zeros(varargin{:},dataType) ;
          test.ones = @(varargin) gpuArray.ones(varargin{:},dataType) ;
          test.toDevice = @(x) gpuArray(x) ;
        case 'cpu'
          test.randn = @(varargin) test.range * randn(varargin{:},dataType) ;
          test.rand = @(varargin) test.range * rand(varargin{:},dataType) ;
          test.zeros = @(varargin) zeros(varargin{:},dataType) ;
          test.ones = @(varargin) ones(varargin{:},dataType) ;
          test.toDevice = @(x) gather(x) ;
      end
    end
  end

  methods (TestMethodSetup)
    function seeds(test)
      seed = 0 ;
      switch test.currentDevice
        case 'gpu'
          parallel.gpu.rng(seed, 'combRecursive') ;
        case 'cpu'
          rng(seed, 'combRecursive') ;
      end
    end
  end

  methods
    function der(test, g, x, dzdy, dzdx, delta, tau)
      if nargin < 7
        tau = [] ;
      end
      dzdx_ = test.toDataType(test.numder(g, x, dzdy, delta)) ;
      test.eq(gather(dzdx_), gather(dzdx), tau) ;
    end

    function eq(test,a,b,tau)
      a = gather(a) ;
      b = gather(b) ;
      if nargin > 3 && ~isempty(tau) && tau < 0
        tau_min = -tau ;
        tau = [] ;
      else
        tau_min = 0 ;
      end