/** Extend or truncate the vector to a specified length. */ private static RVector<?> handleLengthOut( RAbstractVector x, int lengthOut, boolean copyIfSameSize) { if (x.getLength() == lengthOut) { return (RVector<?>) (copyIfSameSize ? x.copy() : x); } return x.copyResized(lengthOut, false); }
@Theory public void testGeneric(UnaryArithmeticFactory factory) { // this should trigger the generic case for (RAbstractVector vector : ALL_VECTORS) { executeArithmetic(factory, vector.copy()); } }
/** Prepare the input vector by replicating its elements. */ private static RVector<?> handleEach(RAbstractVector x, int each) { RVector<?> r = x.createEmptySameType(x.getLength() * each, x.isComplete()); for (int i = 0; i < x.getLength(); i++) { for (int j = i * each; j < (i + 1) * each; j++) { r.transferElementSameType(j, x, i); } } return r; }
@Specialization( guards = { "!copyAllAttributes || target != source", "containsMetadata(source, attrSourceProfiles)" }) public RAbstractVector copySameLength( RAbstractVector target, RAbstractVector source, // @Cached("create()") CopyOfRegAttributesNode copyOfReg, // @Cached("createDim()") RemoveAttributeNode removeDim, // @Cached("createDimNames()") RemoveAttributeNode removeDimNames, // @Cached("create()") InitAttributesNode initAttributes, // @Cached("createNames()") PutAttributeNode putNames, // @Cached("createDim()") PutAttributeNode putDim, // @Cached("createBinaryProfile()") ConditionProfile noDimensions, // @Cached("createBinaryProfile()") ConditionProfile hasNamesSource, // @Cached("createBinaryProfile()") ConditionProfile hasDimNames) { RVector result = target.materialize(); if (copyAllAttributes) { copyOfReg.execute(source, result); } int[] newDimensions = source.getDimensions(); if (noDimensions.profile(newDimensions == null)) { RAttributes attributes = result.getAttributes(); if (attributes != null) { removeDim.execute(attributes); removeDimNames.execute(attributes); result.setInternalDimNames(null); } result.setInternalDimensions(null); RStringVector vecNames = source.getNames(attrSourceProfiles); if (hasNamesSource.profile(vecNames != null)) { putNames.execute(initAttributes.execute(result), vecNames); result.setInternalNames(vecNames); return result; } return result; } putDim.execute( initAttributes.execute(result), RDataFactory.createIntVector(newDimensions, RDataFactory.COMPLETE_VECTOR)); result.setInternalDimensions(newDimensions); RList newDimNames = source.getDimNames(attrSourceProfiles); if (hasDimNames.profile(newDimNames != null)) { result.getAttributes().put(RRuntime.DIMNAMES_ATTR_KEY, newDimNames); newDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX; result.setInternalDimNames(newDimNames); return result; } return result; }
@Theory public void testPlusFolding(RAbstractVector originalOperand) { RAbstractVector operand = originalOperand.copy(); assumeThat(operand, is(not(instanceOf(RScalarVector.class)))); if (operand.getRType() == getArgumentType(operand)) { assertFold(true, operand, PLUS); } else { assertFold(false, operand, PLUS); } }
@Theory public void testVectorResult(UnaryArithmeticFactory factory, RAbstractVector originalOperand) { RAbstractVector operand = originalOperand.copy(); assumeThat(operand, is(not(instanceOf(RScalarVector.class)))); Object result = executeArithmetic(factory, operand); Assert.assertFalse(isPrimitive(result)); assumeThat(result, is(instanceOf(RAbstractVector.class))); RAbstractVector resultCast = (RAbstractVector) result; assertThat(resultCast.getLength(), is(equalTo(operand.getLength()))); }
@Theory public void testCopyAttributes(UnaryArithmeticFactory factory, RAbstractVector originalOperand) { RAbstractVector operand = originalOperand.copy(); // we have to e careful not to change mutable vectors RAbstractVector a = operand.copy(); if (a instanceof RShareable) { ((RShareable) a).incRefCount(); } RVector<?> aMaterialized = a.copy().materialize(); aMaterialized.setAttr("a", "a"); assertAttributes(executeArithmetic(factory, aMaterialized.copy()), "a"); }
@Theory public void testCompleteness(UnaryArithmeticFactory factory, RAbstractVector originalOperand) { RAbstractVector operand = originalOperand.copy(); Object result = executeArithmetic(factory, operand); boolean resultComplete = isPrimitive(result) ? true : ((RAbstractVector) result).isComplete(); if (operand.getLength() == 0) { Assert.assertTrue(resultComplete); } else { boolean expectedComplete = operand.isComplete(); Assert.assertEquals(expectedComplete, resultComplete); } }
@Theory public void testSharing(UnaryArithmeticFactory factory, RAbstractVector originalOperand) { RAbstractVector operand = originalOperand.copy(); // sharing does not work if a is a scalar vector assumeThat(true, is(isShareable(operand, operand.getRType()))); RType resultType = getArgumentType(operand); Object sharedResult = null; if (isShareable(operand, resultType)) { sharedResult = operand; } Object result = executeArithmetic(factory, operand); if (sharedResult == null) { Assert.assertNotSame(operand, result); } else { Assert.assertSame(sharedResult, result); } }
private static void assertAttributes(Object value, String... keys) { if (!(value instanceof RAbstractVector)) { Assert.assertEquals(0, keys.length); return; } RAbstractVector vector = (RAbstractVector) value; Set<String> expectedAttributes = new HashSet<>(Arrays.asList(keys)); DynamicObject attributes = vector.getAttributes(); if (attributes == null) { Assert.assertEquals(0, keys.length); return; } Set<Object> foundAttributes = new HashSet<>(); for (RAttributesLayout.RAttribute attribute : RAttributesLayout.asIterable(attributes)) { foundAttributes.add(attribute.getName()); foundAttributes.add(attribute.getValue()); } Assert.assertEquals(expectedAttributes, foundAttributes); }
private static boolean isShareable(RAbstractVector a, RType resultType) { if (a.getRType() != resultType) { // needs cast -> not shareable return false; } if (a instanceof RShareable) { if (((RShareable) a).isTemporary()) { return true; } } return false; }
@Specialization(guards = {"!copyAllAttributes || target != source", "containsMetadata(source)"}) protected RAbstractVector copySameLength( RAbstractVector target, RAbstractVector source, // @Cached("create()") CopyOfRegAttributesNode copyOfReg, // @Cached("createDim()") RemoveFixedAttributeNode removeDim, // @Cached("createDimNames()") RemoveFixedAttributeNode removeDimNames, // @Cached("create()") InitAttributesNode initAttributes, // @Cached("createNames()") SetFixedAttributeNode putNames, // @Cached("createDim()") SetFixedAttributeNode putDim, // @Cached("createDimNames()") SetFixedAttributeNode putDimNames, // @Cached("createBinaryProfile()") ConditionProfile noDimensions, // @Cached("createBinaryProfile()") ConditionProfile hasNamesSource, // @Cached("createBinaryProfile()") ConditionProfile hasDimNames, @Cached("create()") GetDimAttributeNode getDimsNode) { RVector<?> result = target.materialize(); if (copyAllAttributes) { copyOfReg.execute(source, result); } int[] newDimensions = getDimsNode.getDimensions(source); if (noDimensions.profile(newDimensions == null)) { DynamicObject attributes = result.getAttributes(); if (attributes != null) { removeDim.execute(attributes); removeDimNames.execute(attributes); } RStringVector vecNames = getNamesNode.getNames(source); if (hasNamesSource.profile(vecNames != null)) { putNames.execute(initAttributes.execute(result), vecNames); return result; } return result; } putDim.execute( initAttributes.execute(result), RDataFactory.createIntVector(newDimensions, RDataFactory.COMPLETE_VECTOR)); RList newDimNames = getDimNamesNode.getDimNames(source); if (hasDimNames.profile(newDimNames != null)) { putDimNames.execute(result.getAttributes(), newDimNames); newDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX; return result; } return result; }
/** Replicate the vector a given number of times. */ private RVector<?> handleTimes( RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) { if (oneTimeGiven.profile(times.getLength() == 1)) { // only one times value is given final int howManyTimes = times.getDataAt(0); if (howManyTimes < 0) { errorBranch.enter(); throw invalidTimes(); } if (replicateOnce.profile(howManyTimes == 1)) { return (RVector<?>) (copyIfSameSize ? x.copy() : x); } else { return x.copyResized(x.getLength() * howManyTimes, false); } } else { // times is a vector with several elements if (x.getLength() != times.getLength()) { errorBranch.enter(); invalidTimes(); } // iterate once over the times vector to determine result vector size int resultLength = 0; for (int i = 0; i < times.getLength(); i++) { int t = times.getDataAt(i); if (t < 0) { errorBranch.enter(); throw invalidTimes(); } resultLength += t; } // create and populate result vector RVector<?> r = x.createEmptySameType(resultLength, x.isComplete()); int wp = 0; // write pointer for (int i = 0; i < x.getLength(); i++) { for (int j = 0; j < times.getDataAt(i); ++j, ++wp) { r.transferElementSameType(wp, x, i); } } return r; } }
protected boolean containsMetadata(RAbstractVector vector) { return vector instanceof RVector && hasDimNode.execute(vector) || (copyAllAttributes && vector.getAttributes() != null) || getNamesNode.getNames(vector) != null || getDimNamesNode.getDimNames(vector) != null; }
protected boolean containsMetadata(RAbstractVector vector, RAttributeProfiles attrProfiles) { return vector instanceof RVector && vector.hasDimensions() || (copyAllAttributes && vector.getAttributes() != null) || vector.getNames(attrProfiles) != null || vector.getDimNames(attrProfiles) != null; }
private static RType getArgumentType(RAbstractVector operand) { return RType.maxPrecedence(RType.Integer, operand.getRType()); }
@Specialization protected RIntVector doObject(RAbstractVector xa, boolean useNames) { int[] data = new int[xa.getLength()]; Arrays.fill(data, 1); return createResult(xa, data, useNames); }