@@ -354,3 +354,138 @@ def test_tensordot(shape1, chunk1, block1, shape2, chunk2, block2, chunkres, axe
354354 np .testing .assert_allclose (res_b2_np , res_np , rtol = 1e-5 , atol = 1e-6 )
355355 else :
356356 np .testing .assert_array_equal (res_b2_np , res_np )
357+
358+
359+ @pytest .mark .parametrize (
360+ ("shape1" , "chunk1" , "block1" , "shape2" , "chunk2" , "block2" , "chunkres" , "axis" ),
361+ [
362+ # 1Dx1D->scalar
363+ ((50 ,), (17 ,), (5 ,), (50 ,), (13 ,), (5 ,), (), - 1 ),
364+ # 2Dx2D
365+ (
366+ (30 , 40 ),
367+ (17 , 21 ),
368+ (8 , 10 ),
369+ (30 , 40 ),
370+ (19 , 20 ),
371+ (9 , 10 ),
372+ (10 ,),
373+ - 1 ,
374+ ),
375+ # 3Dx3D
376+ (
377+ (10 , 1 , 5 ),
378+ (9 , 1 , 1 ),
379+ (5 , 1 , 1 ),
380+ (10 , 1 , 1 ),
381+ (4 , 1 , 1 ),
382+ (3 , 1 , 1 ),
383+ (3 , 3 ),
384+ - 2 ,
385+ ),
386+ # 4Dx3D
387+ (
388+ (6 , 7 , 8 , 9 ),
389+ (5 , 6 , 7 , 8 ),
390+ (3 , 3 , 3 , 3 ),
391+ (1 , 7 , 8 , 1 ),
392+ (1 , 7 , 3 , 1 ),
393+ (1 , 3 , 2 , 1 ),
394+ (4 , 5 , 2 ),
395+ - 2 ,
396+ ),
397+ # 2Dx1D->broadcastable to (12, 7)
398+ (
399+ (12 , 7 ),
400+ (11 , 7 ),
401+ (5 , 7 ),
402+ (7 ,),
403+ (5 ,),
404+ (2 ,),
405+ (5 ,),
406+ - 1 ,
407+ ),
408+ # 3Dx2D->broadcastable to (1, 6, 7)
409+ (
410+ (5 , 6 , 7 ),
411+ (4 , 5 , 6 ),
412+ (2 , 3 , 3 ),
413+ (6 , 7 ),
414+ (6 , 4 ),
415+ (3 , 4 ),
416+ (3 , 2 ),
417+ - 2 ,
418+ ),
419+ # 1Dx3D -> broadcastable to (1, 1, 20)
420+ ((20 ,), (9 ,), (4 ,), (20 , 4 , 20 ), (19 , 3 , 5 ), (10 , 2 , 5 ), (10 , 2 ), - 1 ),
421+ # 4Dx4D
422+ (
423+ (5 , 8 , 1 , 8 ),
424+ (4 , 5 , 1 , 7 ),
425+ (2 , 3 , 1 , 4 ),
426+ (1 , 8 , 6 , 8 ),
427+ (1 , 7 , 5 , 5 ),
428+ (1 , 4 , 3 , 5 ),
429+ (2 , 2 , 2 ),
430+ - 3 ,
431+ ),
432+ # 5Dx5D
433+ (
434+ (3 , 4 , 5 , 6 , 7 ),
435+ (2 , 3 , 4 , 5 , 6 ),
436+ (1 , 2 , 2 , 3 , 3 ),
437+ (3 , 1 , 1 , 6 , 7 ),
438+ (2 , 1 , 1 , 3 , 5 ),
439+ (2 , 1 , 1 , 2 , 4 ),
440+ (2 , 2 , 2 , 5 ),
441+ - 2 ,
442+ ),
443+ ],
444+ )
445+ @pytest .mark .parametrize (
446+ "dtype" ,
447+ [
448+ np .int32 ,
449+ np .int64 ,
450+ np .float32 ,
451+ np .float64 ,
452+ ],
453+ )
454+ def test_vecdot (shape1 , chunk1 , block1 , shape2 , chunk2 , block2 , chunkres , axis , dtype ):
455+ # Create operands with requested dtype
456+ a_b2 = blosc2 .arange (0 , np .prod (shape1 ), shape = shape1 , chunks = chunk1 , blocks = block1 , dtype = dtype )
457+ a_np = a_b2 [()] # decompress
458+ b_b2 = blosc2 .arange (0 , np .prod (shape2 ), shape = shape2 , chunks = chunk2 , blocks = block2 , dtype = dtype )
459+ b_np = b_b2 [()] # decompress
460+
461+ # NumPy reference and Blosc2 comparison
462+ np_raised = None
463+ try :
464+ res_np = np .vecdot (a_np , b_np , axis = axis )
465+ except Exception as e :
466+ np_raised = type (e )
467+
468+ if np_raised is not None :
469+ # Expect Blosc2 to raise the same type
470+ with pytest .raises (np_raised ):
471+ blosc2 .vecdot (a_b2 , b_b2 , axis = axis , chunks = chunkres )
472+ else :
473+ # Both should succeed
474+ res_np = np .vecdot (a_np , b_np , axis = axis )
475+ res_b2 = blosc2 .vecdot (a_b2 , b_b2 , axis = axis , chunks = chunkres , fast_path = False ) # test slow path
476+ res_b2_np = res_b2 [...]
477+
478+ # Assertions
479+ assert res_b2_np .shape == res_np .shape
480+ if np .issubdtype (dtype , np .floating ):
481+ np .testing .assert_allclose (res_b2_np , res_np , rtol = 1e-5 , atol = 1e-6 )
482+ else :
483+ np .testing .assert_array_equal (res_b2_np , res_np )
484+
485+ res_b2 = blosc2 .vecdot (a_b2 , b_b2 , axis = axis , chunks = chunkres , fast_path = True ) # test fast path
486+ # Assertions
487+ assert res_b2_np .shape == res_np .shape
488+ if np .issubdtype (dtype , np .floating ):
489+ np .testing .assert_allclose (res_b2_np , res_np , rtol = 1e-5 , atol = 1e-6 )
490+ else :
491+ np .testing .assert_array_equal (res_b2_np , res_np )
0 commit comments