@@ -372,6 +372,48 @@ threadsafe static Function DecimateMinMax(WAVE input, WAVE output, variable idx,
372372 output[ targetLast][ colOut] = V_max
373373End
374374
375+ /// @brief Return the number of threads for `Multithread` given a problem with dimension `dims`
376+ ///
377+ /// The algorithm was developed for "easy" problems on the RHS of MultiThread.
378+ ///
379+ /// Example:
380+ ///
381+ /// \rst
382+ /// .. code-block:: igorpro
383+ ///
384+ /// Make/FREE/N=(1025, 10) data
385+ /// WAVE dims = GetWaveDimensions(data)
386+ /// variable numThreads = GetNumberOfUsefulThreads(dims)
387+ /// MultiThread/Y=(numThreads) data = ...
388+ ///
389+ /// \endrst
390+ threadsafe Function GetNumberOfUsefulThreads ( WAVE dims)
391+
392+ variable pointsPerThread, numCores, numPoints, numThreads, numRows, numCols, i
393+
394+ ASSERT_TS ( WaveExists ( dims) && IsNumericWave ( dims) , "Needs a numeric wave" )
395+
396+ numRows = DimSize ( dims, ROWS)
397+ ASSERT_TS ( numRows <= MAX_DIMENSION_COUNT, "Expected at most MAX_DIMENSION_COUNT rows" )
398+
399+ numCols = DimSize ( dims, COLS)
400+ ASSERT_TS ( numCols <= 1, "Expected a 1D wave" )
401+
402+ pointsPerThread = 4096
403+ numCores = TSDS_ReadVar ( TSDS_PROCCOUNT)
404+
405+ numPoints = 1
406+ for ( i = 0; i < numRows; i += 1 )
407+ numPoints *= max ( 1, dims[ i ])
408+ endfor
409+
410+ numThreads = min ( ceil ( numPoints / pointsPerThread) , numCores)
411+
412+ ASSERT_TS ( IsInteger ( numThreads) && numThreads > 0, "Invalid thread count" )
413+
414+ return numThreads
415+ End
416+
375417/// @brief Extended version of `FindValue`
376418///
377419/// Allows to search only the specified column for a value
404446/// value could not be found.
405447threadsafe Function/WAVE FindIndizes ( WAVE numericOrTextWave, [ variable col, string colLabel, variable var, string str, variable prop, variable startRow, variable endRow, variable startLayer, variable endLayer] )
406448
407- variable numCols, numRows, numLayers, maskedProp
449+ variable numCols, numRows, numLayers, maskedProp, numThreads , numRowsEffective , numLayersEffective
408450 string key
409451
410452 ASSERT_TS (( ParamIsDefault ( prop) && ( ParamIsDefault ( var) + ParamIsDefault ( str)) == 1 ) \
@@ -478,12 +520,13 @@ threadsafe Function/WAVE FindIndizes(WAVE numericOrTextWave, [variable col, stri
478520 endif
479521
480522 if ( ParamIsDefault ( endRow))
481- endRow = Inf
523+ endRow = numRows - 1
482524 else
483525 ASSERT_TS ( endRow >= 0 && endRow < numRows, "Invalid endRow" )
484526 endif
485527
486528 ASSERT_TS ( startRow <= endRow, "endRow must be larger than startRow" )
529+ numRowsEffective = ( endRow - startRow) + 1
487530
488531 if ( ParamIsDefault ( startLayer))
489532 startLayer = 0
@@ -499,94 +542,97 @@ threadsafe Function/WAVE FindIndizes(WAVE numericOrTextWave, [variable col, stri
499542 endif
500543
501544 ASSERT_TS ( startLayer <= endLayer, "endLayer must be larger than startLayer" )
545+ numLayersEffective = ( endLayer - startLayer) + 1
502546
503547 // Algorithm:
504548 // * The matches wave has the same size as one column of the input wave
505549 // * -1 means no match, every value larger or equal than zero is the row index of the match
506550 // * There is no distinction between different layers matching
507551 // * After the matches have been calculated we take the maximum of the transposed matches
508- // wave in each colum transpose back and replace -1 with NaN
552+ // wave in each colum transpose back and replace -1 with NaN. This multiple layer matching algorithm
553+ // using maxCols is also the reason why we can't start with NaN on no match but have to use -1
509554 // * This gives a 1D wave with NaN in the rows with no match, and the row index of the match otherwise
510555 // * Delete all NaNs in the wave and return it
511556
512- key = CA_TemporaryWaveKey ({ numRows, numLayers})
557+ key = CA_FindIndizesKey ({ numRows, numLayers})
513558 WAVE /Z/ D matches = CA_TryFetchingEntryFromCache ( key, options = CA_OPTS_NO_DUPLICATE)
514559
515560 if ( ! WaveExists ( matches))
516561 Make / N= ( numRows, numLayers) / FREE/ D matches
517562 CA_StoreEntryIntoCache ( key, matches, options = CA_OPTS_NO_DUPLICATE)
518563 endif
519564
565+ numThreads = GetNumberOfUsefulThreads ({ numRowsEffective, numLayersEffective})
566+
520567 FastOp matches = -1
521568
522569 if ( WaveExists ( wv))
523570 if ( ! ParamIsDefault ( prop))
524571 if ( prop & PROP_EMPTY)
525572 if ( prop & PROP_NOT)
526- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ( numtype ( wv[ p][ col][ q]) != 2 ) ? p : -1
573+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ( numtype ( wv[ p][ col][ q]) != 2 ) ? p : -1
527574 else
528- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ( numtype ( wv[ p][ col][ q]) == 2 ) ? p : -1
575+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ( numtype ( wv[ p][ col][ q]) == 2 ) ? p : -1
529576 endif
530577 elseif ( prop & PROP_MATCHES_VAR_BIT_MASK)
531578 if ( prop & PROP_NOT)
532- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ! ( wv[ p][ col][ q] & var) ? p : -1
579+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ! ( wv[ p][ col][ q] & var) ? p : -1
533580 else
534- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ( wv[ p][ col][ q] & var) ? p : -1
581+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ( wv[ p][ col][ q] & var) ? p : -1
535582 endif
536583 elseif ( prop & PROP_GREP)
537584 if ( prop & PROP_NOT)
538- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ! GrepString ( num2strHighPrec ( wv[ p][ col][ q]) , str) ? p : -1
585+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ! GrepString ( num2strHighPrec ( wv[ p][ col][ q]) , str) ? p : -1
539586 else
540- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = GrepString ( num2strHighPrec ( wv[ p][ col][ q]) , str) ? p : -1
587+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = GrepString ( num2strHighPrec ( wv[ p][ col][ q]) , str) ? p : -1
541588 endif
542589 elseif ( prop & PROP_WILDCARD)
543590 if ( prop & PROP_NOT)
544- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ! StringMatch ( num2strHighPrec ( wv[ p][ col][ q]) , str) ? p : -1
591+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ! StringMatch ( num2strHighPrec ( wv[ p][ col][ q]) , str) ? p : -1
545592 else
546- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = StringMatch ( num2strHighPrec ( wv[ p][ col][ q]) , str) ? p : -1
593+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = StringMatch ( num2strHighPrec ( wv[ p][ col][ q]) , str) ? p : -1
547594 endif
548595 elseif ( prop & PROP_NOT)
549- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ( wv[ p][ col][ q] != var) ? p : -1
596+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ( wv[ p][ col][ q] != var) ? p : -1
550597 endif
551598 else
552599 ASSERT_TS ( ! IsNaN ( var) , "Use PROP_EMPTY to search for NaN" )
553- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ( wv[ p][ col][ q] == var) ? p : -1
600+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ( wv[ p][ col][ q] == var) ? p : -1
554601 endif
555602 else
556603 if ( ! ParamIsDefault ( prop))
557604 if ( prop & PROP_EMPTY)
558605 if ( prop & PROP_NOT)
559- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = strlen ( wvText[ p][ col][ q]) ? p : -1
606+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = strlen ( wvText[ p][ col][ q]) ? p : -1
560607 else
561- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ! strlen ( wvText[ p][ col][ q]) ? p : -1
608+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ! strlen ( wvText[ p][ col][ q]) ? p : -1
562609 endif
563610 elseif ( prop & PROP_MATCHES_VAR_BIT_MASK)
564611 if ( prop & PROP_NOT)
565- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ! ( str2num ( wvText[ p][ col][ q]) & var) ? p : -1
612+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ! ( str2num ( wvText[ p][ col][ q]) & var) ? p : -1
566613 else
567- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ( str2num ( wvText[ p][ col][ q]) & var) ? p : -1
614+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ( str2num ( wvText[ p][ col][ q]) & var) ? p : -1
568615 endif
569616 elseif ( prop & PROP_GREP)
570617 if ( prop & PROP_NOT)
571- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ! GrepString ( wvText[ p][ col][ q] , str) ? p : -1
618+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ! GrepString ( wvText[ p][ col][ q] , str) ? p : -1
572619 else
573- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = GrepString ( wvText[ p][ col][ q] , str) ? p : -1
620+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = GrepString ( wvText[ p][ col][ q] , str) ? p : -1
574621 endif
575622 elseif ( prop & PROP_WILDCARD)
576623 if ( prop & PROP_NOT)
577- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ! StringMatch ( wvText[ p][ col][ q] , str) ? p : -1
624+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ! StringMatch ( wvText[ p][ col][ q] , str) ? p : -1
578625 else
579- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = StringMatch ( wvText[ p][ col][ q] , str) ? p : -1
626+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = StringMatch ( wvText[ p][ col][ q] , str) ? p : -1
580627 endif
581628 elseif ( prop & PROP_NOT)
582- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = CmpStr ( wvText[ p][ col][ q] , str) ? p : -1
629+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = CmpStr ( wvText[ p][ col][ q] , str) ? p : -1
583630 endif
584631 else
585- MultiThread matches[ startRow, endRow][ startLayer, endLayer] = ! CmpStr ( wvText[ p][ col][ q] , str) ? p : -1
632+ MultiThread / NT = ( numThreads ) matches[ startRow, endRow][ startLayer, endLayer] = ! CmpStr ( wvText[ p][ col][ q] , str) ? p : -1
586633 endif
587634 endif
588635
589- endRow = numRows - 1
590636 MatrixOp / FREE result = zapNans ( replace ( maxCols ( subRange ( matches, startRow, endRow, startLayer, endLayer) ^ t) ^ t, -1, NaN ))
591637
592638 if ( DimSize ( result, ROWS) == 0 )
0 commit comments