github.com/wzzhu/tensor@v0.9.24/defaultengine_arith.go (about)

     1  // Code generated by genlib2. DO NOT EDIT.
     2  
     3  package tensor
     4  
     5  import (
     6  	"github.com/pkg/errors"
     7  	"github.com/wzzhu/tensor/internal/storage"
     8  )
     9  
    10  // Add performs a + b elementwise. Both a and b must have the same shape.
    11  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
    12  func (e StdEng) Add(a Tensor, b Tensor, opts ...FuncOpt) (retVal Tensor, err error) {
    13  	if err = binaryCheck(a, b, numberTypes); err != nil {
    14  		return nil, errors.Wrapf(err, "Add failed")
    15  	}
    16  
    17  	var reuse DenseTensor
    18  	var safe, toReuse, incr bool
    19  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(a.Shape(), a.Dtype(), a.DataOrder(), true, opts...); err != nil {
    20  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
    21  	}
    22  	typ := a.Dtype().Type
    23  	var dataA, dataB, dataReuse *storage.Header
    24  	var ait, bit, iit Iterator
    25  	var useIter, swap bool
    26  	if dataA, dataB, dataReuse, ait, bit, iit, useIter, swap, err = prepDataVV(a, b, reuse); err != nil {
    27  		return nil, errors.Wrapf(err, "StdEng.Add")
    28  	}
    29  	if useIter {
    30  		switch {
    31  		case incr:
    32  			err = e.E.AddIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
    33  			retVal = reuse
    34  		case toReuse:
    35  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
    36  			ait.Reset()
    37  			iit.Reset()
    38  			err = e.E.AddIter(typ, dataReuse, dataB, iit, bit)
    39  			retVal = reuse
    40  		case !safe:
    41  			err = e.E.AddIter(typ, dataA, dataB, ait, bit)
    42  			retVal = a
    43  		default:
    44  			if swap {
    45  				retVal = b.Clone().(Tensor)
    46  			} else {
    47  				retVal = a.Clone().(Tensor)
    48  			}
    49  			err = e.E.AddIter(typ, retVal.hdr(), dataB, ait, bit)
    50  		}
    51  		return
    52  	}
    53  	switch {
    54  	case incr:
    55  		err = e.E.AddIncr(typ, dataA, dataB, dataReuse)
    56  		retVal = reuse
    57  	case toReuse:
    58  		err = e.E.AddRecv(typ, dataA, dataB, dataReuse)
    59  		retVal = reuse
    60  	case !safe:
    61  		err = e.E.Add(typ, dataA, dataB)
    62  		retVal = a
    63  	default:
    64  		if swap {
    65  			retVal = b.Clone().(Tensor)
    66  		} else {
    67  			retVal = a.Clone().(Tensor)
    68  		}
    69  		err = e.E.Add(typ, retVal.hdr(), dataB)
    70  	}
    71  	return
    72  }
    73  
    74  // Sub performs a - b elementwise. Both a and b must have the same shape.
    75  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
    76  func (e StdEng) Sub(a Tensor, b Tensor, opts ...FuncOpt) (retVal Tensor, err error) {
    77  	if err = binaryCheck(a, b, numberTypes); err != nil {
    78  		return nil, errors.Wrapf(err, "Sub failed")
    79  	}
    80  
    81  	var reuse DenseTensor
    82  	var safe, toReuse, incr bool
    83  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(a.Shape(), a.Dtype(), a.DataOrder(), true, opts...); err != nil {
    84  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
    85  	}
    86  	typ := a.Dtype().Type
    87  	var dataA, dataB, dataReuse *storage.Header
    88  	var ait, bit, iit Iterator
    89  	var useIter, swap bool
    90  	if dataA, dataB, dataReuse, ait, bit, iit, useIter, swap, err = prepDataVV(a, b, reuse); err != nil {
    91  		return nil, errors.Wrapf(err, "StdEng.Sub")
    92  	}
    93  	if useIter {
    94  		switch {
    95  		case incr:
    96  			err = e.E.SubIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
    97  			retVal = reuse
    98  		case toReuse:
    99  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   100  			ait.Reset()
   101  			iit.Reset()
   102  			err = e.E.SubIter(typ, dataReuse, dataB, iit, bit)
   103  			retVal = reuse
   104  		case !safe:
   105  			err = e.E.SubIter(typ, dataA, dataB, ait, bit)
   106  			retVal = a
   107  		default:
   108  			if swap {
   109  				retVal = b.Clone().(Tensor)
   110  			} else {
   111  				retVal = a.Clone().(Tensor)
   112  			}
   113  			err = e.E.SubIter(typ, retVal.hdr(), dataB, ait, bit)
   114  		}
   115  		return
   116  	}
   117  	switch {
   118  	case incr:
   119  		err = e.E.SubIncr(typ, dataA, dataB, dataReuse)
   120  		retVal = reuse
   121  	case toReuse:
   122  		err = e.E.SubRecv(typ, dataA, dataB, dataReuse)
   123  		retVal = reuse
   124  	case !safe:
   125  		err = e.E.Sub(typ, dataA, dataB)
   126  		retVal = a
   127  	default:
   128  		if swap {
   129  			retVal = b.Clone().(Tensor)
   130  		} else {
   131  			retVal = a.Clone().(Tensor)
   132  		}
   133  		err = e.E.Sub(typ, retVal.hdr(), dataB)
   134  	}
   135  	return
   136  }
   137  
   138  // Mul performs a × b elementwise. Both a and b must have the same shape.
   139  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   140  func (e StdEng) Mul(a Tensor, b Tensor, opts ...FuncOpt) (retVal Tensor, err error) {
   141  	if err = binaryCheck(a, b, numberTypes); err != nil {
   142  		return nil, errors.Wrapf(err, "Mul failed")
   143  	}
   144  
   145  	var reuse DenseTensor
   146  	var safe, toReuse, incr bool
   147  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(a.Shape(), a.Dtype(), a.DataOrder(), true, opts...); err != nil {
   148  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   149  	}
   150  	typ := a.Dtype().Type
   151  	var dataA, dataB, dataReuse *storage.Header
   152  	var ait, bit, iit Iterator
   153  	var useIter, swap bool
   154  	if dataA, dataB, dataReuse, ait, bit, iit, useIter, swap, err = prepDataVV(a, b, reuse); err != nil {
   155  		return nil, errors.Wrapf(err, "StdEng.Mul")
   156  	}
   157  	if useIter {
   158  		switch {
   159  		case incr:
   160  			err = e.E.MulIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   161  			retVal = reuse
   162  		case toReuse:
   163  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   164  			ait.Reset()
   165  			iit.Reset()
   166  			err = e.E.MulIter(typ, dataReuse, dataB, iit, bit)
   167  			retVal = reuse
   168  		case !safe:
   169  			err = e.E.MulIter(typ, dataA, dataB, ait, bit)
   170  			retVal = a
   171  		default:
   172  			if swap {
   173  				retVal = b.Clone().(Tensor)
   174  			} else {
   175  				retVal = a.Clone().(Tensor)
   176  			}
   177  			err = e.E.MulIter(typ, retVal.hdr(), dataB, ait, bit)
   178  		}
   179  		return
   180  	}
   181  	switch {
   182  	case incr:
   183  		err = e.E.MulIncr(typ, dataA, dataB, dataReuse)
   184  		retVal = reuse
   185  	case toReuse:
   186  		err = e.E.MulRecv(typ, dataA, dataB, dataReuse)
   187  		retVal = reuse
   188  	case !safe:
   189  		err = e.E.Mul(typ, dataA, dataB)
   190  		retVal = a
   191  	default:
   192  		if swap {
   193  			retVal = b.Clone().(Tensor)
   194  		} else {
   195  			retVal = a.Clone().(Tensor)
   196  		}
   197  		err = e.E.Mul(typ, retVal.hdr(), dataB)
   198  	}
   199  	return
   200  }
   201  
   202  // Div performs a ÷ b elementwise. Both a and b must have the same shape.
   203  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   204  func (e StdEng) Div(a Tensor, b Tensor, opts ...FuncOpt) (retVal Tensor, err error) {
   205  	if err = binaryCheck(a, b, numberTypes); err != nil {
   206  		return nil, errors.Wrapf(err, "Div failed")
   207  	}
   208  
   209  	var reuse DenseTensor
   210  	var safe, toReuse, incr bool
   211  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(a.Shape(), a.Dtype(), a.DataOrder(), true, opts...); err != nil {
   212  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   213  	}
   214  	typ := a.Dtype().Type
   215  	var dataA, dataB, dataReuse *storage.Header
   216  	var ait, bit, iit Iterator
   217  	var useIter, swap bool
   218  	if dataA, dataB, dataReuse, ait, bit, iit, useIter, swap, err = prepDataVV(a, b, reuse); err != nil {
   219  		return nil, errors.Wrapf(err, "StdEng.Div")
   220  	}
   221  	if useIter {
   222  		switch {
   223  		case incr:
   224  			err = e.E.DivIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   225  			retVal = reuse
   226  		case toReuse:
   227  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   228  			ait.Reset()
   229  			iit.Reset()
   230  			err = e.E.DivIter(typ, dataReuse, dataB, iit, bit)
   231  			retVal = reuse
   232  		case !safe:
   233  			err = e.E.DivIter(typ, dataA, dataB, ait, bit)
   234  			retVal = a
   235  		default:
   236  			if swap {
   237  				retVal = b.Clone().(Tensor)
   238  			} else {
   239  				retVal = a.Clone().(Tensor)
   240  			}
   241  			err = e.E.DivIter(typ, retVal.hdr(), dataB, ait, bit)
   242  		}
   243  		return
   244  	}
   245  	switch {
   246  	case incr:
   247  		err = e.E.DivIncr(typ, dataA, dataB, dataReuse)
   248  		retVal = reuse
   249  	case toReuse:
   250  		err = e.E.DivRecv(typ, dataA, dataB, dataReuse)
   251  		retVal = reuse
   252  	case !safe:
   253  		err = e.E.Div(typ, dataA, dataB)
   254  		retVal = a
   255  	default:
   256  		if swap {
   257  			retVal = b.Clone().(Tensor)
   258  		} else {
   259  			retVal = a.Clone().(Tensor)
   260  		}
   261  		err = e.E.Div(typ, retVal.hdr(), dataB)
   262  	}
   263  	return
   264  }
   265  
   266  // Pow performs a ^ b elementwise. Both a and b must have the same shape.
   267  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   268  func (e StdEng) Pow(a Tensor, b Tensor, opts ...FuncOpt) (retVal Tensor, err error) {
   269  	if err = binaryCheck(a, b, numberTypes); err != nil {
   270  		return nil, errors.Wrapf(err, "Pow failed")
   271  	}
   272  
   273  	var reuse DenseTensor
   274  	var safe, toReuse, incr bool
   275  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(a.Shape(), a.Dtype(), a.DataOrder(), true, opts...); err != nil {
   276  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   277  	}
   278  	typ := a.Dtype().Type
   279  	var dataA, dataB, dataReuse *storage.Header
   280  	var ait, bit, iit Iterator
   281  	var useIter, swap bool
   282  	if dataA, dataB, dataReuse, ait, bit, iit, useIter, swap, err = prepDataVV(a, b, reuse); err != nil {
   283  		return nil, errors.Wrapf(err, "StdEng.Pow")
   284  	}
   285  	if useIter {
   286  		switch {
   287  		case incr:
   288  			err = e.E.PowIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   289  			retVal = reuse
   290  		case toReuse:
   291  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   292  			ait.Reset()
   293  			iit.Reset()
   294  			err = e.E.PowIter(typ, dataReuse, dataB, iit, bit)
   295  			retVal = reuse
   296  		case !safe:
   297  			err = e.E.PowIter(typ, dataA, dataB, ait, bit)
   298  			retVal = a
   299  		default:
   300  			if swap {
   301  				retVal = b.Clone().(Tensor)
   302  			} else {
   303  				retVal = a.Clone().(Tensor)
   304  			}
   305  			err = e.E.PowIter(typ, retVal.hdr(), dataB, ait, bit)
   306  		}
   307  		return
   308  	}
   309  	switch {
   310  	case incr:
   311  		err = e.E.PowIncr(typ, dataA, dataB, dataReuse)
   312  		retVal = reuse
   313  	case toReuse:
   314  		err = e.E.PowRecv(typ, dataA, dataB, dataReuse)
   315  		retVal = reuse
   316  	case !safe:
   317  		err = e.E.Pow(typ, dataA, dataB)
   318  		retVal = a
   319  	default:
   320  		if swap {
   321  			retVal = b.Clone().(Tensor)
   322  		} else {
   323  			retVal = a.Clone().(Tensor)
   324  		}
   325  		err = e.E.Pow(typ, retVal.hdr(), dataB)
   326  	}
   327  	return
   328  }
   329  
   330  // Mod performs a % b elementwise. Both a and b must have the same shape.
   331  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   332  func (e StdEng) Mod(a Tensor, b Tensor, opts ...FuncOpt) (retVal Tensor, err error) {
   333  	if err = binaryCheck(a, b, numberTypes); err != nil {
   334  		return nil, errors.Wrapf(err, "Mod failed")
   335  	}
   336  
   337  	var reuse DenseTensor
   338  	var safe, toReuse, incr bool
   339  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(a.Shape(), a.Dtype(), a.DataOrder(), true, opts...); err != nil {
   340  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   341  	}
   342  	typ := a.Dtype().Type
   343  	var dataA, dataB, dataReuse *storage.Header
   344  	var ait, bit, iit Iterator
   345  	var useIter, swap bool
   346  	if dataA, dataB, dataReuse, ait, bit, iit, useIter, swap, err = prepDataVV(a, b, reuse); err != nil {
   347  		return nil, errors.Wrapf(err, "StdEng.Mod")
   348  	}
   349  	if useIter {
   350  		switch {
   351  		case incr:
   352  			err = e.E.ModIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   353  			retVal = reuse
   354  		case toReuse:
   355  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   356  			ait.Reset()
   357  			iit.Reset()
   358  			err = e.E.ModIter(typ, dataReuse, dataB, iit, bit)
   359  			retVal = reuse
   360  		case !safe:
   361  			err = e.E.ModIter(typ, dataA, dataB, ait, bit)
   362  			retVal = a
   363  		default:
   364  			if swap {
   365  				retVal = b.Clone().(Tensor)
   366  			} else {
   367  				retVal = a.Clone().(Tensor)
   368  			}
   369  			err = e.E.ModIter(typ, retVal.hdr(), dataB, ait, bit)
   370  		}
   371  		return
   372  	}
   373  	switch {
   374  	case incr:
   375  		err = e.E.ModIncr(typ, dataA, dataB, dataReuse)
   376  		retVal = reuse
   377  	case toReuse:
   378  		err = e.E.ModRecv(typ, dataA, dataB, dataReuse)
   379  		retVal = reuse
   380  	case !safe:
   381  		err = e.E.Mod(typ, dataA, dataB)
   382  		retVal = a
   383  	default:
   384  		if swap {
   385  			retVal = b.Clone().(Tensor)
   386  		} else {
   387  			retVal = a.Clone().(Tensor)
   388  		}
   389  		err = e.E.Mod(typ, retVal.hdr(), dataB)
   390  	}
   391  	return
   392  }
   393  
   394  // AddScalar performs t + s elementwise. The leftTensor parameter indicates if the tensor is the left operand. Only scalar types are accepted in s.
   395  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   396  func (e StdEng) AddScalar(t Tensor, s interface{}, leftTensor bool, opts ...FuncOpt) (retVal Tensor, err error) {
   397  	if err = unaryCheck(t, numberTypes); err != nil {
   398  		return nil, errors.Wrapf(err, "Add failed")
   399  	}
   400  
   401  	if err = scalarDtypeCheck(t, s); err != nil {
   402  		return nil, errors.Wrap(err, "Add failed")
   403  	}
   404  
   405  	var reuse DenseTensor
   406  	var safe, toReuse, incr bool
   407  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(t.Shape(), t.Dtype(), t.DataOrder(), true, opts...); err != nil {
   408  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   409  	}
   410  	a := t
   411  	typ := t.Dtype().Type
   412  	var ait, bit, iit Iterator
   413  	var dataA, dataB, dataReuse, scalarHeader *storage.Header
   414  	var useIter, newAlloc bool
   415  
   416  	if leftTensor {
   417  		if dataA, dataB, dataReuse, ait, iit, useIter, newAlloc, err = prepDataVS(t, s, reuse); err != nil {
   418  			return nil, errors.Wrapf(err, opFail, "StdEng.Add")
   419  		}
   420  		scalarHeader = dataB
   421  	} else {
   422  		if dataA, dataB, dataReuse, bit, iit, useIter, newAlloc, err = prepDataSV(s, t, reuse); err != nil {
   423  			return nil, errors.Wrapf(err, opFail, "StdEng.Add")
   424  		}
   425  		scalarHeader = dataA
   426  	}
   427  
   428  	if useIter {
   429  		switch {
   430  		case incr:
   431  			err = e.E.AddIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   432  			retVal = reuse
   433  		case toReuse && leftTensor:
   434  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   435  			ait.Reset()
   436  			iit.Reset()
   437  			err = e.E.AddIter(typ, dataReuse, dataB, iit, bit)
   438  			retVal = reuse
   439  		case toReuse && !leftTensor:
   440  			storage.CopyIter(typ, dataReuse, dataB, iit, bit)
   441  			iit.Reset()
   442  			bit.Reset()
   443  			err = e.E.AddIter(typ, dataA, dataReuse, ait, iit)
   444  			retVal = reuse
   445  		case !safe:
   446  			err = e.E.AddIter(typ, dataA, dataB, ait, bit)
   447  			retVal = a
   448  		default:
   449  			retVal = a.Clone().(Tensor)
   450  			if leftTensor {
   451  				err = e.E.AddIter(typ, retVal.hdr(), dataB, ait, bit)
   452  			} else {
   453  				err = e.E.AddIter(typ, dataA, retVal.hdr(), ait, bit)
   454  			}
   455  		}
   456  		if newAlloc {
   457  			freeScalar(scalarHeader.Raw)
   458  		}
   459  		returnHeader(scalarHeader)
   460  		return
   461  	}
   462  	switch {
   463  	case incr:
   464  		err = e.E.AddIncr(typ, dataA, dataB, dataReuse)
   465  		retVal = reuse
   466  	case toReuse && leftTensor:
   467  		storage.Copy(typ, dataReuse, dataA)
   468  		err = e.E.Add(typ, dataReuse, dataB)
   469  		retVal = reuse
   470  	case toReuse && !leftTensor:
   471  		storage.Copy(typ, dataReuse, dataB)
   472  		err = e.E.Add(typ, dataA, dataReuse)
   473  		if t.Shape().IsScalarEquiv() {
   474  			storage.Copy(typ, dataReuse, dataA)
   475  		}
   476  		retVal = reuse
   477  	case !safe:
   478  		err = e.E.Add(typ, dataA, dataB)
   479  		if t.Shape().IsScalarEquiv() && !leftTensor {
   480  			storage.Copy(typ, dataB, dataA)
   481  		}
   482  		retVal = a
   483  	default:
   484  		retVal = a.Clone().(Tensor)
   485  		if !leftTensor {
   486  			storage.Fill(typ, retVal.hdr(), dataA)
   487  		}
   488  		err = e.E.Add(typ, retVal.hdr(), dataB)
   489  	}
   490  	if newAlloc {
   491  		freeScalar(scalarHeader.Raw)
   492  	}
   493  	returnHeader(scalarHeader)
   494  	return
   495  }
   496  
   497  // SubScalar performs t - s elementwise. The leftTensor parameter indicates if the tensor is the left operand. Only scalar types are accepted in s.
   498  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   499  func (e StdEng) SubScalar(t Tensor, s interface{}, leftTensor bool, opts ...FuncOpt) (retVal Tensor, err error) {
   500  	if err = unaryCheck(t, numberTypes); err != nil {
   501  		return nil, errors.Wrapf(err, "Sub failed")
   502  	}
   503  
   504  	if err = scalarDtypeCheck(t, s); err != nil {
   505  		return nil, errors.Wrap(err, "Sub failed")
   506  	}
   507  
   508  	var reuse DenseTensor
   509  	var safe, toReuse, incr bool
   510  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(t.Shape(), t.Dtype(), t.DataOrder(), true, opts...); err != nil {
   511  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   512  	}
   513  	a := t
   514  	typ := t.Dtype().Type
   515  	var ait, bit, iit Iterator
   516  	var dataA, dataB, dataReuse, scalarHeader *storage.Header
   517  	var useIter, newAlloc bool
   518  
   519  	if leftTensor {
   520  		if dataA, dataB, dataReuse, ait, iit, useIter, newAlloc, err = prepDataVS(t, s, reuse); err != nil {
   521  			return nil, errors.Wrapf(err, opFail, "StdEng.Sub")
   522  		}
   523  		scalarHeader = dataB
   524  	} else {
   525  		if dataA, dataB, dataReuse, bit, iit, useIter, newAlloc, err = prepDataSV(s, t, reuse); err != nil {
   526  			return nil, errors.Wrapf(err, opFail, "StdEng.Sub")
   527  		}
   528  		scalarHeader = dataA
   529  	}
   530  
   531  	if useIter {
   532  		switch {
   533  		case incr:
   534  			err = e.E.SubIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   535  			retVal = reuse
   536  		case toReuse && leftTensor:
   537  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   538  			ait.Reset()
   539  			iit.Reset()
   540  			err = e.E.SubIter(typ, dataReuse, dataB, iit, bit)
   541  			retVal = reuse
   542  		case toReuse && !leftTensor:
   543  			storage.CopyIter(typ, dataReuse, dataB, iit, bit)
   544  			iit.Reset()
   545  			bit.Reset()
   546  			err = e.E.SubIter(typ, dataA, dataReuse, ait, iit)
   547  			retVal = reuse
   548  		case !safe:
   549  			err = e.E.SubIter(typ, dataA, dataB, ait, bit)
   550  			retVal = a
   551  		default:
   552  			retVal = a.Clone().(Tensor)
   553  			if leftTensor {
   554  				err = e.E.SubIter(typ, retVal.hdr(), dataB, ait, bit)
   555  			} else {
   556  				err = e.E.SubIter(typ, dataA, retVal.hdr(), ait, bit)
   557  			}
   558  		}
   559  		if newAlloc {
   560  			freeScalar(scalarHeader.Raw)
   561  		}
   562  		returnHeader(scalarHeader)
   563  		return
   564  	}
   565  	switch {
   566  	case incr:
   567  		err = e.E.SubIncr(typ, dataA, dataB, dataReuse)
   568  		retVal = reuse
   569  	case toReuse && leftTensor:
   570  		storage.Copy(typ, dataReuse, dataA)
   571  		err = e.E.Sub(typ, dataReuse, dataB)
   572  		retVal = reuse
   573  	case toReuse && !leftTensor:
   574  		storage.Copy(typ, dataReuse, dataB)
   575  		err = e.E.Sub(typ, dataA, dataReuse)
   576  		if t.Shape().IsScalarEquiv() {
   577  			storage.Copy(typ, dataReuse, dataA)
   578  		}
   579  		retVal = reuse
   580  	case !safe:
   581  		err = e.E.Sub(typ, dataA, dataB)
   582  		if t.Shape().IsScalarEquiv() && !leftTensor {
   583  			storage.Copy(typ, dataB, dataA)
   584  		}
   585  		retVal = a
   586  	default:
   587  		retVal = a.Clone().(Tensor)
   588  		if !leftTensor {
   589  			storage.Fill(typ, retVal.hdr(), dataA)
   590  		}
   591  		err = e.E.Sub(typ, retVal.hdr(), dataB)
   592  	}
   593  	if newAlloc {
   594  		freeScalar(scalarHeader.Raw)
   595  	}
   596  	returnHeader(scalarHeader)
   597  	return
   598  }
   599  
   600  // MulScalar performs t × s elementwise. The leftTensor parameter indicates if the tensor is the left operand. Only scalar types are accepted in s.
   601  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   602  func (e StdEng) MulScalar(t Tensor, s interface{}, leftTensor bool, opts ...FuncOpt) (retVal Tensor, err error) {
   603  	if err = unaryCheck(t, numberTypes); err != nil {
   604  		return nil, errors.Wrapf(err, "Mul failed")
   605  	}
   606  
   607  	if err = scalarDtypeCheck(t, s); err != nil {
   608  		return nil, errors.Wrap(err, "Mul failed")
   609  	}
   610  
   611  	var reuse DenseTensor
   612  	var safe, toReuse, incr bool
   613  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(t.Shape(), t.Dtype(), t.DataOrder(), true, opts...); err != nil {
   614  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   615  	}
   616  	a := t
   617  	typ := t.Dtype().Type
   618  	var ait, bit, iit Iterator
   619  	var dataA, dataB, dataReuse, scalarHeader *storage.Header
   620  	var useIter, newAlloc bool
   621  
   622  	if leftTensor {
   623  		if dataA, dataB, dataReuse, ait, iit, useIter, newAlloc, err = prepDataVS(t, s, reuse); err != nil {
   624  			return nil, errors.Wrapf(err, opFail, "StdEng.Mul")
   625  		}
   626  		scalarHeader = dataB
   627  	} else {
   628  		if dataA, dataB, dataReuse, bit, iit, useIter, newAlloc, err = prepDataSV(s, t, reuse); err != nil {
   629  			return nil, errors.Wrapf(err, opFail, "StdEng.Mul")
   630  		}
   631  		scalarHeader = dataA
   632  	}
   633  
   634  	if useIter {
   635  		switch {
   636  		case incr:
   637  			err = e.E.MulIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   638  			retVal = reuse
   639  		case toReuse && leftTensor:
   640  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   641  			ait.Reset()
   642  			iit.Reset()
   643  			err = e.E.MulIter(typ, dataReuse, dataB, iit, bit)
   644  			retVal = reuse
   645  		case toReuse && !leftTensor:
   646  			storage.CopyIter(typ, dataReuse, dataB, iit, bit)
   647  			iit.Reset()
   648  			bit.Reset()
   649  			err = e.E.MulIter(typ, dataA, dataReuse, ait, iit)
   650  			retVal = reuse
   651  		case !safe:
   652  			err = e.E.MulIter(typ, dataA, dataB, ait, bit)
   653  			retVal = a
   654  		default:
   655  			retVal = a.Clone().(Tensor)
   656  			if leftTensor {
   657  				err = e.E.MulIter(typ, retVal.hdr(), dataB, ait, bit)
   658  			} else {
   659  				err = e.E.MulIter(typ, dataA, retVal.hdr(), ait, bit)
   660  			}
   661  		}
   662  		if newAlloc {
   663  			freeScalar(scalarHeader.Raw)
   664  		}
   665  		returnHeader(scalarHeader)
   666  		return
   667  	}
   668  	switch {
   669  	case incr:
   670  		err = e.E.MulIncr(typ, dataA, dataB, dataReuse)
   671  		retVal = reuse
   672  	case toReuse && leftTensor:
   673  		storage.Copy(typ, dataReuse, dataA)
   674  		err = e.E.Mul(typ, dataReuse, dataB)
   675  		retVal = reuse
   676  	case toReuse && !leftTensor:
   677  		storage.Copy(typ, dataReuse, dataB)
   678  		err = e.E.Mul(typ, dataA, dataReuse)
   679  		if t.Shape().IsScalarEquiv() {
   680  			storage.Copy(typ, dataReuse, dataA)
   681  		}
   682  		retVal = reuse
   683  	case !safe:
   684  		err = e.E.Mul(typ, dataA, dataB)
   685  		if t.Shape().IsScalarEquiv() && !leftTensor {
   686  			storage.Copy(typ, dataB, dataA)
   687  		}
   688  		retVal = a
   689  	default:
   690  		retVal = a.Clone().(Tensor)
   691  		if !leftTensor {
   692  			storage.Fill(typ, retVal.hdr(), dataA)
   693  		}
   694  		err = e.E.Mul(typ, retVal.hdr(), dataB)
   695  	}
   696  	if newAlloc {
   697  		freeScalar(scalarHeader.Raw)
   698  	}
   699  	returnHeader(scalarHeader)
   700  	return
   701  }
   702  
   703  // DivScalar performs t ÷ s elementwise. The leftTensor parameter indicates if the tensor is the left operand. Only scalar types are accepted in s.
   704  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   705  func (e StdEng) DivScalar(t Tensor, s interface{}, leftTensor bool, opts ...FuncOpt) (retVal Tensor, err error) {
   706  	if err = unaryCheck(t, numberTypes); err != nil {
   707  		return nil, errors.Wrapf(err, "Div failed")
   708  	}
   709  
   710  	if err = scalarDtypeCheck(t, s); err != nil {
   711  		return nil, errors.Wrap(err, "Div failed")
   712  	}
   713  
   714  	var reuse DenseTensor
   715  	var safe, toReuse, incr bool
   716  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(t.Shape(), t.Dtype(), t.DataOrder(), true, opts...); err != nil {
   717  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   718  	}
   719  	a := t
   720  	typ := t.Dtype().Type
   721  	var ait, bit, iit Iterator
   722  	var dataA, dataB, dataReuse, scalarHeader *storage.Header
   723  	var useIter, newAlloc bool
   724  
   725  	if leftTensor {
   726  		if dataA, dataB, dataReuse, ait, iit, useIter, newAlloc, err = prepDataVS(t, s, reuse); err != nil {
   727  			return nil, errors.Wrapf(err, opFail, "StdEng.Div")
   728  		}
   729  		scalarHeader = dataB
   730  	} else {
   731  		if dataA, dataB, dataReuse, bit, iit, useIter, newAlloc, err = prepDataSV(s, t, reuse); err != nil {
   732  			return nil, errors.Wrapf(err, opFail, "StdEng.Div")
   733  		}
   734  		scalarHeader = dataA
   735  	}
   736  
   737  	if useIter {
   738  		switch {
   739  		case incr:
   740  			err = e.E.DivIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   741  			retVal = reuse
   742  		case toReuse && leftTensor:
   743  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   744  			ait.Reset()
   745  			iit.Reset()
   746  			err = e.E.DivIter(typ, dataReuse, dataB, iit, bit)
   747  			retVal = reuse
   748  		case toReuse && !leftTensor:
   749  			storage.CopyIter(typ, dataReuse, dataB, iit, bit)
   750  			iit.Reset()
   751  			bit.Reset()
   752  			err = e.E.DivIter(typ, dataA, dataReuse, ait, iit)
   753  			retVal = reuse
   754  		case !safe:
   755  			err = e.E.DivIter(typ, dataA, dataB, ait, bit)
   756  			retVal = a
   757  		default:
   758  			retVal = a.Clone().(Tensor)
   759  			if leftTensor {
   760  				err = e.E.DivIter(typ, retVal.hdr(), dataB, ait, bit)
   761  			} else {
   762  				err = e.E.DivIter(typ, dataA, retVal.hdr(), ait, bit)
   763  			}
   764  		}
   765  		if newAlloc {
   766  			freeScalar(scalarHeader.Raw)
   767  		}
   768  		returnHeader(scalarHeader)
   769  		return
   770  	}
   771  	switch {
   772  	case incr:
   773  		err = e.E.DivIncr(typ, dataA, dataB, dataReuse)
   774  		retVal = reuse
   775  	case toReuse && leftTensor:
   776  		storage.Copy(typ, dataReuse, dataA)
   777  		err = e.E.Div(typ, dataReuse, dataB)
   778  		retVal = reuse
   779  	case toReuse && !leftTensor:
   780  		storage.Copy(typ, dataReuse, dataB)
   781  		err = e.E.Div(typ, dataA, dataReuse)
   782  		if t.Shape().IsScalarEquiv() {
   783  			storage.Copy(typ, dataReuse, dataA)
   784  		}
   785  		retVal = reuse
   786  	case !safe:
   787  		err = e.E.Div(typ, dataA, dataB)
   788  		if t.Shape().IsScalarEquiv() && !leftTensor {
   789  			storage.Copy(typ, dataB, dataA)
   790  		}
   791  		retVal = a
   792  	default:
   793  		retVal = a.Clone().(Tensor)
   794  		if !leftTensor {
   795  			storage.Fill(typ, retVal.hdr(), dataA)
   796  		}
   797  		err = e.E.Div(typ, retVal.hdr(), dataB)
   798  	}
   799  	if newAlloc {
   800  		freeScalar(scalarHeader.Raw)
   801  	}
   802  	returnHeader(scalarHeader)
   803  	return
   804  }
   805  
   806  // PowScalar performs t ^ s elementwise. The leftTensor parameter indicates if the tensor is the left operand. Only scalar types are accepted in s.
   807  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   808  func (e StdEng) PowScalar(t Tensor, s interface{}, leftTensor bool, opts ...FuncOpt) (retVal Tensor, err error) {
   809  	if err = unaryCheck(t, numberTypes); err != nil {
   810  		return nil, errors.Wrapf(err, "Pow failed")
   811  	}
   812  
   813  	if err = scalarDtypeCheck(t, s); err != nil {
   814  		return nil, errors.Wrap(err, "Pow failed")
   815  	}
   816  
   817  	var reuse DenseTensor
   818  	var safe, toReuse, incr bool
   819  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(t.Shape(), t.Dtype(), t.DataOrder(), true, opts...); err != nil {
   820  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   821  	}
   822  	a := t
   823  	typ := t.Dtype().Type
   824  	var ait, bit, iit Iterator
   825  	var dataA, dataB, dataReuse, scalarHeader *storage.Header
   826  	var useIter, newAlloc bool
   827  
   828  	if leftTensor {
   829  		if dataA, dataB, dataReuse, ait, iit, useIter, newAlloc, err = prepDataVS(t, s, reuse); err != nil {
   830  			return nil, errors.Wrapf(err, opFail, "StdEng.Pow")
   831  		}
   832  		scalarHeader = dataB
   833  	} else {
   834  		if dataA, dataB, dataReuse, bit, iit, useIter, newAlloc, err = prepDataSV(s, t, reuse); err != nil {
   835  			return nil, errors.Wrapf(err, opFail, "StdEng.Pow")
   836  		}
   837  		scalarHeader = dataA
   838  	}
   839  
   840  	if useIter {
   841  		switch {
   842  		case incr:
   843  			err = e.E.PowIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   844  			retVal = reuse
   845  		case toReuse && leftTensor:
   846  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   847  			ait.Reset()
   848  			iit.Reset()
   849  			err = e.E.PowIter(typ, dataReuse, dataB, iit, bit)
   850  			retVal = reuse
   851  		case toReuse && !leftTensor:
   852  			storage.CopyIter(typ, dataReuse, dataB, iit, bit)
   853  			iit.Reset()
   854  			bit.Reset()
   855  			err = e.E.PowIter(typ, dataA, dataReuse, ait, iit)
   856  			retVal = reuse
   857  		case !safe:
   858  			err = e.E.PowIter(typ, dataA, dataB, ait, bit)
   859  			retVal = a
   860  		default:
   861  			retVal = a.Clone().(Tensor)
   862  			if leftTensor {
   863  				err = e.E.PowIter(typ, retVal.hdr(), dataB, ait, bit)
   864  			} else {
   865  				err = e.E.PowIter(typ, dataA, retVal.hdr(), ait, bit)
   866  			}
   867  		}
   868  		if newAlloc {
   869  			freeScalar(scalarHeader.Raw)
   870  		}
   871  		returnHeader(scalarHeader)
   872  		return
   873  	}
   874  	switch {
   875  	case incr:
   876  		err = e.E.PowIncr(typ, dataA, dataB, dataReuse)
   877  		retVal = reuse
   878  	case toReuse && leftTensor:
   879  		storage.Copy(typ, dataReuse, dataA)
   880  		err = e.E.Pow(typ, dataReuse, dataB)
   881  		retVal = reuse
   882  	case toReuse && !leftTensor:
   883  		storage.Copy(typ, dataReuse, dataB)
   884  		err = e.E.Pow(typ, dataA, dataReuse)
   885  		if t.Shape().IsScalarEquiv() {
   886  			storage.Copy(typ, dataReuse, dataA)
   887  		}
   888  		retVal = reuse
   889  	case !safe:
   890  		err = e.E.Pow(typ, dataA, dataB)
   891  		if t.Shape().IsScalarEquiv() && !leftTensor {
   892  			storage.Copy(typ, dataB, dataA)
   893  		}
   894  		retVal = a
   895  	default:
   896  		retVal = a.Clone().(Tensor)
   897  		if !leftTensor {
   898  			storage.Fill(typ, retVal.hdr(), dataA)
   899  		}
   900  		err = e.E.Pow(typ, retVal.hdr(), dataB)
   901  	}
   902  	if newAlloc {
   903  		freeScalar(scalarHeader.Raw)
   904  	}
   905  	returnHeader(scalarHeader)
   906  	return
   907  }
   908  
   909  // ModScalar performs t % s elementwise. The leftTensor parameter indicates if the tensor is the left operand. Only scalar types are accepted in s.
   910  // Acceptable FuncOpts are: UseUnsafe(), WithReuse(T), WithIncr(T)
   911  func (e StdEng) ModScalar(t Tensor, s interface{}, leftTensor bool, opts ...FuncOpt) (retVal Tensor, err error) {
   912  	if err = unaryCheck(t, numberTypes); err != nil {
   913  		return nil, errors.Wrapf(err, "Mod failed")
   914  	}
   915  
   916  	if err = scalarDtypeCheck(t, s); err != nil {
   917  		return nil, errors.Wrap(err, "Mod failed")
   918  	}
   919  
   920  	var reuse DenseTensor
   921  	var safe, toReuse, incr bool
   922  	if reuse, safe, toReuse, incr, _, err = handleFuncOpts(t.Shape(), t.Dtype(), t.DataOrder(), true, opts...); err != nil {
   923  		return nil, errors.Wrap(err, "Unable to handle funcOpts")
   924  	}
   925  	a := t
   926  	typ := t.Dtype().Type
   927  	var ait, bit, iit Iterator
   928  	var dataA, dataB, dataReuse, scalarHeader *storage.Header
   929  	var useIter, newAlloc bool
   930  
   931  	if leftTensor {
   932  		if dataA, dataB, dataReuse, ait, iit, useIter, newAlloc, err = prepDataVS(t, s, reuse); err != nil {
   933  			return nil, errors.Wrapf(err, opFail, "StdEng.Mod")
   934  		}
   935  		scalarHeader = dataB
   936  	} else {
   937  		if dataA, dataB, dataReuse, bit, iit, useIter, newAlloc, err = prepDataSV(s, t, reuse); err != nil {
   938  			return nil, errors.Wrapf(err, opFail, "StdEng.Mod")
   939  		}
   940  		scalarHeader = dataA
   941  	}
   942  
   943  	if useIter {
   944  		switch {
   945  		case incr:
   946  			err = e.E.ModIterIncr(typ, dataA, dataB, dataReuse, ait, bit, iit)
   947  			retVal = reuse
   948  		case toReuse && leftTensor:
   949  			storage.CopyIter(typ, dataReuse, dataA, iit, ait)
   950  			ait.Reset()
   951  			iit.Reset()
   952  			err = e.E.ModIter(typ, dataReuse, dataB, iit, bit)
   953  			retVal = reuse
   954  		case toReuse && !leftTensor:
   955  			storage.CopyIter(typ, dataReuse, dataB, iit, bit)
   956  			iit.Reset()
   957  			bit.Reset()
   958  			err = e.E.ModIter(typ, dataA, dataReuse, ait, iit)
   959  			retVal = reuse
   960  		case !safe:
   961  			err = e.E.ModIter(typ, dataA, dataB, ait, bit)
   962  			retVal = a
   963  		default:
   964  			retVal = a.Clone().(Tensor)
   965  			if leftTensor {
   966  				err = e.E.ModIter(typ, retVal.hdr(), dataB, ait, bit)
   967  			} else {
   968  				err = e.E.ModIter(typ, dataA, retVal.hdr(), ait, bit)
   969  			}
   970  		}
   971  		if newAlloc {
   972  			freeScalar(scalarHeader.Raw)
   973  		}
   974  		returnHeader(scalarHeader)
   975  		return
   976  	}
   977  	switch {
   978  	case incr:
   979  		err = e.E.ModIncr(typ, dataA, dataB, dataReuse)
   980  		retVal = reuse
   981  	case toReuse && leftTensor:
   982  		storage.Copy(typ, dataReuse, dataA)
   983  		err = e.E.Mod(typ, dataReuse, dataB)
   984  		retVal = reuse
   985  	case toReuse && !leftTensor:
   986  		storage.Copy(typ, dataReuse, dataB)
   987  		err = e.E.Mod(typ, dataA, dataReuse)
   988  		if t.Shape().IsScalarEquiv() {
   989  			storage.Copy(typ, dataReuse, dataA)
   990  		}
   991  		retVal = reuse
   992  	case !safe:
   993  		err = e.E.Mod(typ, dataA, dataB)
   994  		if t.Shape().IsScalarEquiv() && !leftTensor {
   995  			storage.Copy(typ, dataB, dataA)
   996  		}
   997  		retVal = a
   998  	default:
   999  		retVal = a.Clone().(Tensor)
  1000  		if !leftTensor {
  1001  			storage.Fill(typ, retVal.hdr(), dataA)
  1002  		}
  1003  		err = e.E.Mod(typ, retVal.hdr(), dataB)
  1004  	}
  1005  	if newAlloc {
  1006  		freeScalar(scalarHeader.Raw)
  1007  	}
  1008  	returnHeader(scalarHeader)
  1009  	return
  1010  }