or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

array-operations.mdcuda-integration.mdfft.mdindex.mdindexing-selection.mdinput-output.mdjit-kernels.mdlinear-algebra.mdlogic-operations.mdmathematical-functions.mdrandom-generation.mdscipy-extensions.mdstatistics.mdtesting.md

indexing-selection.mddocs/

0

# Indexing and Selection

1

2

Advanced indexing, selection, and extraction operations including fancy indexing, boolean indexing, and element insertion for flexible array manipulation. CuPy provides comprehensive GPU-accelerated indexing capabilities with NumPy compatibility for complex data selection patterns.

3

4

## Capabilities

5

6

### Basic Indexing and Slicing

7

8

Fundamental array indexing operations for accessing and modifying array elements.

9

10

```python { .api }

11

def take(a, indices, axis=None, out=None, mode='raise'):

12

"""Take elements from array along specified axis.

13

14

Args:

15

a: Input array

16

indices: Indices of elements to take

17

axis: Axis along which to take elements

18

out: Output array

19

mode: How to handle out-of-bounds indices ('raise', 'wrap', 'clip')

20

21

Returns:

22

cupy.ndarray: Selected elements

23

"""

24

25

def take_along_axis(arr, indices, axis):

26

"""Take values from input array by matching 1D index array.

27

28

Args:

29

arr: Input array

30

indices: Indices array with same ndim as arr

31

axis: Axis along which to take values

32

33

Returns:

34

cupy.ndarray: Selected values

35

"""

36

37

def compress(condition, a, axis=None, out=None):

38

"""Select slices along axis using boolean condition.

39

40

Args:

41

condition: Boolean 1-D array selecting slices

42

a: Input array

43

axis: Axis along which to select

44

out: Output array

45

46

Returns:

47

cupy.ndarray: Compressed array

48

"""

49

50

def diagonal(a, offset=0, axis1=0, axis2=1):

51

"""Extract diagonal elements from 2-D array.

52

53

Args:

54

a: Input array (≥2D)

55

offset: Diagonal offset (0 for main diagonal)

56

axis1: First axis for diagonal

57

axis2: Second axis for diagonal

58

59

Returns:

60

cupy.ndarray: Diagonal elements

61

"""

62

63

def diag(v, k=0):

64

"""Extract diagonal or construct diagonal array.

65

66

Args:

67

v: Input array or 1-D array for diagonal construction

68

k: Diagonal offset

69

70

Returns:

71

cupy.ndarray: Diagonal elements or diagonal matrix

72

"""

73

```

74

75

### Advanced Selection

76

77

Sophisticated selection methods for complex data access patterns.

78

79

```python { .api }

80

def choose(a, choices, out=None, mode='raise'):

81

"""Use index array to construct new array from choice arrays.

82

83

Args:

84

a: Index array (integers)

85

choices: Sequence of arrays to choose from

86

out: Output array

87

mode: How to handle out-of-bounds indices

88

89

Returns:

90

cupy.ndarray: Array constructed from choices

91

"""

92

93

def select(condlist, choicelist, default=0):

94

"""Select elements from choicelist based on conditions.

95

96

Args:

97

condlist: List of boolean conditions

98

choicelist: List of arrays/scalars to choose from

99

default: Default value when no condition is True

100

101

Returns:

102

cupy.ndarray: Array with selected elements

103

"""

104

105

def extract(condition, arr):

106

"""Extract elements satisfying condition.

107

108

Args:

109

condition: Boolean array or condition

110

arr: Input array

111

112

Returns:

113

cupy.ndarray: 1-D array of elements where condition is True

114

"""

115

116

def where(condition, x=None, y=None):

117

"""Select elements from x or y based on condition.

118

119

Args:

120

condition: Boolean array condition

121

x: Array/scalar for True elements

122

y: Array/scalar for False elements

123

124

Returns:

125

cupy.ndarray or tuple: Selected elements or indices

126

"""

127

```

128

129

### Index Generation and Utilities

130

131

Functions for generating and manipulating array indices.

132

133

```python { .api }

134

def indices(dimensions, dtype=int, sparse=False):

135

"""Return grid of indices for given dimensions.

136

137

Args:

138

dimensions: Shape of output grid

139

dtype: Data type for indices

140

sparse: Return sparse representation

141

142

Returns:

143

cupy.ndarray: Grid indices array

144

"""

145

146

def ix_(*args):

147

"""Construct open mesh from multiple sequences.

148

149

Args:

150

*args: 1-D sequences for each dimension

151

152

Returns:

153

tuple: Tuple of arrays for open mesh indexing

154

"""

155

156

def ravel_multi_index(multi_index, dims, mode='raise', order='C'):

157

"""Convert multi-dimensional index to flat index.

158

159

Args:

160

multi_index: Tuple of index arrays

161

dims: Shape of array being indexed

162

mode: How to handle out-of-bounds indices

163

order: Memory layout ('C' or 'F')

164

165

Returns:

166

cupy.ndarray: Flat indices

167

"""

168

169

def unravel_index(indices, shape, order='C'):

170

"""Convert flat index to multi-dimensional index.

171

172

Args:

173

indices: Flat index array

174

shape: Shape to unravel into

175

order: Memory layout ('C' or 'F')

176

177

Returns:

178

tuple: Tuple of index arrays

179

"""

180

181

def nonzero(a):

182

"""Return indices of non-zero elements.

183

184

Args:

185

a: Input array

186

187

Returns:

188

tuple: Tuple of index arrays for each dimension

189

"""

190

191

def flatnonzero(a):

192

"""Return indices of non-zero elements in flattened array.

193

194

Args:

195

a: Input array

196

197

Returns:

198

cupy.ndarray: 1-D array of flat indices

199

"""

200

201

def argwhere(a):

202

"""Return indices of non-zero elements grouped by element.

203

204

Args:

205

a: Input array

206

207

Returns:

208

cupy.ndarray: 2-D array where each row is an index

209

"""

210

```

211

212

### Searching and Sorting Indices

213

214

Functions for finding extrema, sorting, and searching within arrays.

215

216

```python { .api }

217

def argmax(a, axis=None, out=None, keepdims=False):

218

"""Indices of maximum values along axis.

219

220

Args:

221

a: Input array

222

axis: Axis for computation

223

out: Output array

224

keepdims: Keep reduced dimensions

225

226

Returns:

227

cupy.ndarray: Indices of maximum elements

228

"""

229

230

def argmin(a, axis=None, out=None, keepdims=False):

231

"""Indices of minimum values along axis.

232

233

Args:

234

a: Input array

235

axis: Axis for computation

236

out: Output array

237

keepdims: Keep reduced dimensions

238

239

Returns:

240

cupy.ndarray: Indices of minimum elements

241

"""

242

243

def nanargmax(a, axis=None, out=None, keepdims=False):

244

"""Indices of maximum values ignoring NaNs.

245

246

Args:

247

a: Input array

248

axis: Axis for computation

249

out: Output array

250

keepdims: Keep reduced dimensions

251

252

Returns:

253

cupy.ndarray: Indices of maximum elements (ignoring NaN)

254

"""

255

256

def nanargmin(a, axis=None, out=None, keepdims=False):

257

"""Indices of minimum values ignoring NaNs.

258

259

Args:

260

a: Input array

261

axis: Axis for computation

262

out: Output array

263

keepdims: Keep reduced dimensions

264

265

Returns:

266

cupy.ndarray: Indices of minimum elements (ignoring NaN)

267

"""

268

269

def argsort(a, axis=-1, kind=None, order=None):

270

"""Indices that would sort array along axis.

271

272

Args:

273

a: Input array

274

axis: Axis to sort along

275

kind: Sorting algorithm (None, 'quicksort', 'mergesort', 'heapsort')

276

order: Field order for structured arrays

277

278

Returns:

279

cupy.ndarray: Array of indices that sort input

280

"""

281

282

def argpartition(a, kth, axis=-1, kind='introselect', order=None):

283

"""Indices that partition array around kth element.

284

285

Args:

286

a: Input array

287

kth: Element index around which to partition

288

axis: Axis to partition along

289

kind: Partitioning algorithm

290

order: Field order for structured arrays

291

292

Returns:

293

cupy.ndarray: Array of partition indices

294

"""

295

296

def searchsorted(a, v, side='left', sorter=None):

297

"""Find indices to insert elements to maintain sorted order.

298

299

Args:

300

a: Input sorted array

301

v: Values to insert

302

side: Insert position ('left' or 'right')

303

sorter: Optional array of indices that sort a

304

305

Returns:

306

cupy.ndarray: Insertion indices

307

"""

308

```

309

310

### Element Insertion and Modification

311

312

Functions for inserting, placing, and modifying array elements.

313

314

```python { .api }

315

def put(a, ind, v, mode='raise'):

316

"""Put values into array at specified indices.

317

318

Args:

319

a: Target array (modified in-place)

320

ind: Target indices

321

v: Values to insert

322

mode: How to handle out-of-bounds indices

323

"""

324

325

def place(arr, mask, vals):

326

"""Place values into array based on boolean mask.

327

328

Args:

329

arr: Target array (modified in-place)

330

mask: Boolean array indicating positions

331

vals: Values to place

332

"""

333

334

def putmask(a, mask, values):

335

"""Put values where mask is True.

336

337

Args:

338

a: Target array (modified in-place)

339

mask: Boolean mask

340

values: Replacement values

341

"""

342

343

def fill_diagonal(a, val, wrap=False):

344

"""Fill main diagonal of array.

345

346

Args:

347

a: Array to modify (≥2D)

348

val: Value to fill diagonal with

349

wrap: Wrap diagonal for non-square arrays

350

"""

351

352

def diag_indices(n, ndim=2):

353

"""Return indices for diagonal elements.

354

355

Args:

356

n: Size of arrays for which indices are returned

357

ndim: Number of dimensions

358

359

Returns:

360

tuple: Indices for diagonal elements

361

"""

362

363

def diag_indices_from(arr):

364

"""Return indices for diagonal of n-dimensional array.

365

366

Args:

367

arr: Input array

368

369

Returns:

370

tuple: Indices for diagonal elements

371

"""

372

```

373

374

### Masking and Conditional Operations

375

376

Advanced masking operations for selective array processing.

377

378

```python { .api }

379

def mask_indices(n, mask_func, k=0):

380

"""Return indices for masking based on function.

381

382

Args:

383

n: Number of rows/columns in output

384

mask_func: Function defining mask pattern

385

k: Optional parameter for mask function

386

387

Returns:

388

tuple: Indices satisfying mask condition

389

"""

390

391

def tril_indices(n, k=0, m=None):

392

"""Return indices for lower triangle of array.

393

394

Args:

395

n: Number of rows in output

396

k: Diagonal offset

397

m: Number of columns (defaults to n)

398

399

Returns:

400

tuple: Lower triangle indices

401

"""

402

403

def tril_indices_from(arr, k=0):

404

"""Return indices for lower triangle of given array.

405

406

Args:

407

arr: Input array

408

k: Diagonal offset

409

410

Returns:

411

tuple: Lower triangle indices

412

"""

413

414

def triu_indices(n, k=0, m=None):

415

"""Return indices for upper triangle of array.

416

417

Args:

418

n: Number of rows in output

419

k: Diagonal offset

420

m: Number of columns (defaults to n)

421

422

Returns:

423

tuple: Upper triangle indices

424

"""

425

426

def triu_indices_from(arr, k=0):

427

"""Return indices for upper triangle of given array.

428

429

Args:

430

arr: Input array

431

k: Diagonal offset

432

433

Returns:

434

tuple: Upper triangle indices

435

"""

436

437

def meshgrid(*xi, copy=True, sparse=False, indexing='xy'):

438

"""Create coordinate arrays from coordinate vectors.

439

440

Args:

441

*xi: 1-D arrays for coordinates

442

copy: Return copies of input arrays

443

sparse: Return sparse grid

444

indexing: Cartesian ('xy') or matrix ('ij') indexing

445

446

Returns:

447

list: Coordinate arrays

448

"""

449

```

450

451

### Iterator Objects

452

453

Iterator classes for advanced array traversal patterns.

454

455

```python { .api }

456

class flatiter:

457

"""Iterator for flattened array.

458

459

Provides iteration over array as if it were 1-dimensional.

460

461

Attributes:

462

base: Base array being iterated

463

coords: Current coordinates

464

index: Current flat index

465

"""

466

467

def __iter__(self):

468

"""Return iterator object."""

469

pass

470

471

def __next__(self):

472

"""Get next element."""

473

pass

474

475

def __getitem__(self, key):

476

"""Get element(s) by index/slice."""

477

pass

478

479

def __setitem__(self, key, value):

480

"""Set element(s) by index/slice."""

481

pass

482

483

class nditer:

484

"""Multi-dimensional iterator object.

485

486

Args:

487

op: Array(s) to iterate over

488

flags: Iteration flags

489

op_flags: Per-operand flags

490

op_dtypes: Per-operand data types

491

order: Iteration order

492

casting: Casting rule

493

op_axes: Per-operand axes

494

itershape: Iteration shape

495

buffersize: Buffer size

496

497

Provides advanced iteration patterns with broadcasting,

498

buffering, and multi-array iteration.

499

"""

500

501

def __init__(self, op, flags=None, op_flags=None, op_dtypes=None,

502

order='K', casting='safe', op_axes=None, itershape=None,

503

buffersize=0):

504

pass

505

```

506

507

## Usage Examples

508

509

### Basic Indexing and Selection

510

511

```python

512

import cupy as cp

513

514

# Create sample array

515

data = cp.arange(24).reshape(4, 6)

516

print(f"Original array:\n{data}")

517

518

# Basic indexing

519

element = data[1, 3] # Single element

520

row = data[2] # Entire row

521

column = data[:, 1] # Entire column

522

subarray = data[1:3, 2:5] # Rectangular slice

523

524

print(f"Element [1,3]: {element}")

525

print(f"Row 2: {row}")

526

print(f"Column 1: {column}")

527

print(f"Subarray [1:3, 2:5]:\n{subarray}")

528

529

# Take elements by indices

530

indices = cp.array([0, 2, 1, 3])

531

taken_rows = cp.take(data, indices, axis=0)

532

taken_elements = cp.take(data.flatten(), cp.array([5, 10, 15, 20]))

533

534

print(f"Taken rows (indices {indices}):\n{taken_rows}")

535

print(f"Taken elements: {taken_elements}")

536

537

# Diagonal extraction

538

diag_main = cp.diagonal(data) # Main diagonal

539

diag_upper = cp.diagonal(data, offset=1) # Upper diagonal

540

diag_lower = cp.diagonal(data, offset=-1) # Lower diagonal

541

542

print(f"Main diagonal: {diag_main}")

543

print(f"Upper diagonal: {diag_upper}")

544

print(f"Lower diagonal: {diag_lower}")

545

```

546

547

### Boolean and Fancy Indexing

548

549

```python

550

import cupy as cp

551

552

# Create test data

553

temperatures = cp.array([18.5, 22.1, 28.7, 31.4, 19.8, 25.3, 33.1, 16.9])

554

cities = cp.array(['NYC', 'LA', 'MIA', 'PHX', 'SEA', 'CHI', 'LAS', 'BOS'])

555

556

# Boolean indexing

557

hot_weather = temperatures > 25

558

cold_weather = temperatures < 20

559

moderate_weather = (temperatures >= 20) & (temperatures <= 30)

560

561

hot_cities = cities[hot_weather]

562

cold_cities = cities[cold_weather]

563

hot_temps = temperatures[hot_weather]

564

565

print(f"Hot cities (>25°C): {hot_cities}")

566

print(f"Hot temperatures: {hot_temps}")

567

print(f"Cold cities (<20°C): {cold_cities}")

568

569

# Fancy indexing with arrays

570

indices = cp.array([1, 3, 5, 7]) # Select specific indices

571

selected_temps = temperatures[indices]

572

selected_cities = cities[indices]

573

574

print(f"Selected temperatures: {selected_temps}")

575

print(f"Selected cities: {selected_cities}")

576

577

# Multi-dimensional boolean indexing

578

matrix = cp.random.randn(5, 8)

579

positive = matrix > 0

580

negative = matrix < 0

581

extreme = cp.abs(matrix) > 1.5

582

583

print(f"Matrix shape: {matrix.shape}")

584

print(f"Positive elements: {cp.sum(positive)}")

585

print(f"Negative elements: {cp.sum(negative)}")

586

print(f"Extreme values: {cp.sum(extreme)}")

587

588

# Extract extreme values and their positions

589

extreme_values = matrix[extreme]

590

extreme_positions = cp.argwhere(extreme)

591

592

print(f"First 5 extreme values: {extreme_values[:5]}")

593

print(f"First 5 extreme positions:\n{extreme_positions[:5]}")

594

```

595

596

### Advanced Selection with where and choose

597

598

```python

599

import cupy as cp

600

601

# Sample data - student scores

602

math_scores = cp.array([85, 92, 76, 88, 91, 73, 95, 82])

603

english_scores = cp.array([78, 89, 94, 82, 86, 88, 91, 79])

604

science_scores = cp.array([90, 87, 81, 95, 89, 76, 93, 85])

605

606

# Use where for conditional selection

607

# Select higher of math or english score for each student

608

higher_score = cp.where(math_scores > english_scores, math_scores, english_scores)

609

610

print(f"Math scores: {math_scores}")

611

print(f"English scores: {english_scores}")

612

print(f"Higher scores: {higher_score}")

613

614

# Multi-condition selection with where

615

# Assign letter grades based on best score

616

best_scores = cp.maximum(cp.maximum(math_scores, english_scores), science_scores)

617

grades = cp.where(best_scores >= 90, 'A',

618

cp.where(best_scores >= 80, 'B',

619

cp.where(best_scores >= 70, 'C', 'F')))

620

621

print(f"Best scores: {best_scores}")

622

print(f"Grades: {grades}")

623

624

# Using choose for more complex selection

625

# Choose subject based on student preference (0=math, 1=english, 2=science)

626

preferences = cp.array([0, 2, 1, 0, 2, 1, 0, 1]) # Student preferences

627

score_arrays = cp.array([math_scores, english_scores, science_scores])

628

preferred_scores = cp.choose(preferences, score_arrays)

629

630

print(f"Preferences: {preferences}")

631

print(f"Preferred scores: {preferred_scores}")

632

633

# Using select for multiple conditions

634

conditions = [

635

best_scores >= 95, # Excellent

636

best_scores >= 85, # Good

637

best_scores >= 75, # Fair

638

]

639

choices = ['Excellent', 'Good', 'Fair']

640

performance = cp.select(conditions, choices, default='Poor')

641

642

print(f"Performance ratings: {performance}")

643

```

644

645

### Finding and Extracting Elements

646

647

```python

648

import cupy as cp

649

650

# Create sample dataset

651

data = cp.random.randn(1000, 10)

652

outlier_threshold = 2.5

653

654

# Find indices of extremes

655

max_indices = cp.argmax(data, axis=1) # Max in each row

656

min_indices = cp.argmin(data, axis=1) # Min in each row

657

overall_max_idx = cp.argmax(data) # Overall max (flat index)

658

overall_min_idx = cp.argmin(data) # Overall min (flat index)

659

660

print(f"Data shape: {data.shape}")

661

print(f"Overall max at flat index: {overall_max_idx}")

662

print(f"Overall min at flat index: {overall_min_idx}")

663

664

# Convert flat indices to 2D coordinates

665

max_coords = cp.unravel_index(overall_max_idx, data.shape)

666

min_coords = cp.unravel_index(overall_min_idx, data.shape)

667

668

print(f"Max at coordinates: {max_coords}")

669

print(f"Min at coordinates: {min_coords}")

670

print(f"Max value: {data[max_coords]:.3f}")

671

print(f"Min value: {data[min_coords]:.3f}")

672

673

# Find outliers (values beyond threshold)

674

outliers_mask = cp.abs(data) > outlier_threshold

675

outlier_positions = cp.argwhere(outliers_mask)

676

outlier_values = data[outliers_mask]

677

678

print(f"Number of outliers: {len(outlier_values)}")

679

print(f"First 5 outlier positions:\n{outlier_positions[:5]}")

680

print(f"First 5 outlier values: {outlier_values[:5]}")

681

682

# Non-zero elements

683

nonzero_mask = data != 0

684

nonzero_indices = cp.nonzero(nonzero_mask)

685

nonzero_count = len(nonzero_indices[0])

686

687

print(f"Non-zero elements: {nonzero_count}/{data.size}")

688

689

# Extract elements satisfying complex conditions

690

condition = (data > 0) & (cp.abs(data) < 1.0) # Positive values between 0 and 1

691

extracted = cp.extract(condition, data)

692

693

print(f"Values between 0 and 1: {len(extracted)}")

694

print(f"Mean of extracted values: {cp.mean(extracted):.3f}")

695

```

696

697

### Sorting and Searching

698

699

```python

700

import cupy as cp

701

702

# Create unsorted data

703

scores = cp.array([87, 92, 76, 88, 91, 73, 95, 82, 89, 78])

704

names = cp.array(['Alice', 'Bob', 'Charlie', 'David', 'Eve',

705

'Frank', 'Grace', 'Henry', 'Iris', 'Jack'])

706

707

print(f"Original scores: {scores}")

708

print(f"Original names: {names}")

709

710

# Get indices that would sort the scores

711

sort_indices = cp.argsort(scores)

712

reverse_sort_indices = cp.argsort(-scores) # Descending order

713

714

sorted_scores = scores[sort_indices]

715

sorted_names = names[sort_indices]

716

top_scores = scores[reverse_sort_indices]

717

top_names = names[reverse_sort_indices]

718

719

print(f"Sorted scores (ascending): {sorted_scores}")

720

print(f"Sorted names (by score): {sorted_names}")

721

print(f"Top scores (descending): {top_scores}")

722

print(f"Top names (by score): {top_names}")

723

724

# Partial sorting - find top 3 students

725

top_k = 3

726

top_k_indices = cp.argpartition(-scores, top_k)[:top_k]

727

top_k_scores = scores[top_k_indices]

728

top_k_names = names[top_k_indices]

729

730

# Sort the top k for proper ranking

731

top_k_order = cp.argsort(-top_k_scores)

732

final_top_scores = top_k_scores[top_k_order]

733

final_top_names = top_k_names[top_k_order]

734

735

print(f"Top {top_k} scores: {final_top_scores}")

736

print(f"Top {top_k} names: {final_top_names}")

737

738

# Searching in sorted array

739

target_scores = cp.array([80, 90, 95])

740

sorted_scores = cp.sort(scores)

741

742

# Find insertion positions

743

insert_left = cp.searchsorted(sorted_scores, target_scores, side='left')

744

insert_right = cp.searchsorted(sorted_scores, target_scores, side='right')

745

746

print(f"Sorted scores: {sorted_scores}")

747

print(f"Target scores: {target_scores}")

748

print(f"Insert positions (left): {insert_left}")

749

print(f"Insert positions (right): {insert_right}")

750

751

# Count how many scores are below each target

752

below_count = insert_left

753

print(f"Scores below targets: {below_count}")

754

```

755

756

### Multi-dimensional Indexing and Meshgrids

757

758

```python

759

import cupy as cp

760

761

# Create coordinate grids

762

x = cp.linspace(-2, 2, 5)

763

y = cp.linspace(-1, 1, 4)

764

765

# Create meshgrid for function evaluation

766

X, Y = cp.meshgrid(x, y)

767

print(f"X coordinates:\n{X}")

768

print(f"Y coordinates:\n{Y}")

769

770

# Evaluate function over grid

771

Z = X**2 + Y**2 # Distance from origin squared

772

print(f"Function values:\n{Z}")

773

774

# Advanced indexing with meshgrid

775

# Select elements where distance is less than 2

776

distance_mask = Z < 2.0

777

selected_X = X[distance_mask]

778

selected_Y = Y[distance_mask]

779

selected_Z = Z[distance_mask]

780

781

print(f"Selected coordinates (distance < 2):")

782

print(f"X: {selected_X}")

783

print(f"Y: {selected_Y}")

784

print(f"Z: {selected_Z}")

785

786

# Open mesh indexing with ix_

787

rows = cp.array([0, 2])

788

cols = cp.array([1, 3, 4])

789

row_idx, col_idx = cp.ix_(rows, cols)

790

791

print(f"Open mesh indices:")

792

print(f"Row indices:\n{row_idx}")

793

print(f"Col indices:\n{col_idx}")

794

795

# Use open mesh to index into array

796

data = cp.arange(20).reshape(4, 5)

797

selected = data[row_idx, col_idx]

798

print(f"Original data:\n{data}")

799

print(f"Selected subarray:\n{selected}")

800

801

# Multi-dimensional index operations

802

shape = (6, 8)

803

flat_indices = cp.array([5, 12, 25, 33, 41])

804

multi_indices = cp.unravel_index(flat_indices, shape)

805

806

print(f"Flat indices: {flat_indices}")

807

print(f"Multi-dimensional indices:")

808

print(f" Row indices: {multi_indices[0]}")

809

print(f" Col indices: {multi_indices[1]}")

810

811

# Convert back to flat indices

812

recovered_flat = cp.ravel_multi_index(multi_indices, shape)

813

print(f"Recovered flat indices: {recovered_flat}")

814

```

815

816

### Array Modification and Masking

817

818

```python

819

import cupy as cp

820

821

# Create sample array

822

data = cp.random.randn(6, 8)

823

print(f"Original data shape: {data.shape}")

824

print(f"Original data (first 3 rows):\n{data[:3]}")

825

826

# Boolean masking for modification

827

# Replace negative values with zero

828

negative_mask = data < 0

829

data_clipped = data.copy()

830

data_clipped[negative_mask] = 0

831

832

print(f"Negative elements: {cp.sum(negative_mask)}")

833

print(f"After clipping negatives (first 3 rows):\n{data_clipped[:3]}")

834

835

# Use place for conditional replacement

836

data_replaced = data.copy()

837

outlier_mask = cp.abs(data) > 2.0

838

cp.place(data_replaced, outlier_mask, cp.nan)

839

840

print(f"Outlier elements: {cp.sum(outlier_mask)}")

841

print(f"Outliers replaced with NaN: {cp.sum(cp.isnan(data_replaced))}")

842

843

# Use putmask for different replacement strategy

844

data_putmask = data.copy()

845

extreme_mask = cp.abs(data) > 1.5

846

replacement_values = cp.sign(data) * 1.5 # Cap at ±1.5

847

cp.putmask(data_putmask, extreme_mask, replacement_values[extreme_mask])

848

849

print(f"Values capped at ±1.5")

850

print(f"Max absolute value: {cp.max(cp.abs(data_putmask)):.3f}")

851

852

# Direct indexing for complex modifications

853

# Set border elements to specific value

854

border_value = -999

855

data_border = data.copy()

856

data_border[0, :] = border_value # Top row

857

data_border[-1, :] = border_value # Bottom row

858

data_border[:, 0] = border_value # Left column

859

data_border[:, -1] = border_value # Right column

860

861

print(f"Border elements set to {border_value}")

862

print(f"Modified array:\n{data_border}")

863

864

# Diagonal operations

865

square_data = data[:6, :6] # Make it square

866

cp.fill_diagonal(square_data, 0)

867

diag_indices = cp.diag_indices(6)

868

square_data[diag_indices] = cp.arange(6) * 10 # Set diagonal to multiples of 10

869

870

print(f"Modified diagonal:\n{square_data}")

871

872

# Triangle operations

873

upper_tri_indices = cp.triu_indices(6, k=1)

874

lower_tri_indices = cp.tril_indices(6, k=-1)

875

876

tri_data = cp.zeros((6, 6))

877

tri_data[upper_tri_indices] = 1 # Upper triangle

878

tri_data[lower_tri_indices] = -1 # Lower triangle

879

880

print(f"Triangle pattern:\n{tri_data}")

881

```

882

883

### Performance-Optimized Indexing

884

885

```python

886

import cupy as cp

887

import time

888

889

# Large dataset for performance testing

890

n = 1_000_000

891

large_data = cp.random.randn(n)

892

indices = cp.random.randint(0, n, size=100_000)

893

894

print(f"Performance test with {n:,} elements")

895

896

# Time different indexing methods

897

methods = [

898

('Direct indexing', lambda: large_data[indices]),

899

('Take method', lambda: cp.take(large_data, indices)),

900

('Boolean masking', lambda: large_data[large_data > 0]),

901

('Where condition', lambda: cp.where(large_data > 0, large_data, 0)),

902

('Compress', lambda: cp.compress(large_data > 0, large_data)),

903

]

904

905

for name, method in methods:

906

start_time = time.perf_counter()

907

result = method()

908

cp.cuda.Stream.null.synchronize() # Wait for GPU

909

end_time = time.perf_counter()

910

911

print(f"{name:16}: {(end_time - start_time)*1000:6.2f} ms, "

912

f"result size: {result.size:8,}")

913

914

# Memory-efficient indexing patterns

915

# Process large array in chunks to avoid memory issues

916

chunk_size = 100_000

917

results = []

918

919

print(f"\nChunked processing:")

920

for i in range(0, n, chunk_size):

921

chunk_end = min(i + chunk_size, n)

922

chunk = large_data[i:chunk_end]

923

924

# Process chunk (example: find outliers)

925

outliers = chunk[cp.abs(chunk) > 2.0]

926

if len(outliers) > 0:

927

results.append(outliers)

928

929

if i // chunk_size < 5: # Show first few chunks

930

print(f"Chunk {i//chunk_size + 1}: "

931

f"processed {chunk_end - i:6,} elements, "

932

f"found {len(outliers):3} outliers")

933

934

if results:

935

all_outliers = cp.concatenate(results)

936

print(f"Total outliers found: {len(all_outliers)}")

937

else:

938

print("No outliers found")

939

```