[Vm-dev] VM Maker: VMMaker.oscog-eem.3015.mcz

commits at source.squeak.org commits at source.squeak.org
Tue Aug 3 00:44:24 UTC 2021


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3015.mcz

==================== Summary ====================

Name: VMMaker.oscog-eem.3015
Author: eem
Time: 2 August 2021, 5:43:30.36731 pm
UUID: 2f7fd362-d443-4e59-9725-ebc5b7b3fcc1
Ancestors: VMMaker.oscog-eem.3014

Have the CroquetPlugin primitives use the FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag flags.  Use the methodReturnFoo: protocol.

=============== Diff against VMMaker.oscog-eem.3014 ===============

Item was changed:
  ----- Method: B3DAcceleratorPlugin>>stackMatrix: (in category 'primitive support') -----
  stackMatrix: index
  	"Load a 4x4 transformation matrix from the interpreter stack.
  	Return a pointer to the matrix data if successful, nil otherwise."
  	| oop |
+ 	<inline: #always>
+ 	oop := interpreterProxy stackValue: index.
+ 	((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = 16]) ifTrue:
+ 		[^interpreterProxy firstIndexableField: oop].
+ 	interpreterProxy primitiveFail.
- 	<inline: false>
- 	<returnTypeC:'void*'>
- 	oop := interpreterProxy stackObjectValue: index.
- 	oop = nil ifTrue:[^nil].
- 	((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = 16])
- 		ifTrue:[^interpreterProxy firstIndexableField: oop].
  	^nil!

Item was changed:
  ----- Method: CroquetPlugin>>primitiveARC4Transform (in category 'cryptography') -----
  primitiveARC4Transform
  	"Perform an ARC4 transform of input.
  	Arguments:
  		buffer		<ByteArray> transformed data
  		startIndex 	<Integer>	start of transform
  		stopIndex	<Integer>	end of transform
  		m			<ByteArray>	key stream data
  		x			<Integer>	key state value
  		y			<Integer>	key state value
  	Return value:
  		x at y - updated key state value
  	"
  
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)> "Align in case the compiler identifies and generates vector instructions"
  	| y x mOop stopIndex startIndex bufOop bufSize buffer a m b mask ptOop xOop yOop |
+ 	<var: 'buffer' type: #'unsigned char *'>
+ 	<var: 'm' type: #'unsigned char *'>
- 	<export: true>
- 	<var: 'buffer' type: 'unsigned char *'>
- 	<var: 'm' type: 'unsigned char *'>
  
  	interpreterProxy methodArgumentCount = 6
  		ifFalse:[^interpreterProxy primitiveFail].
  	"pick up arguments"
  	y := interpreterProxy stackIntegerValue: 0.
  	x := interpreterProxy stackIntegerValue: 1.
+ 	mOop := interpreterProxy stackValue: 2.
- 	mOop := interpreterProxy stackObjectValue: 2.
  	stopIndex := interpreterProxy stackIntegerValue: 3.
  	startIndex := interpreterProxy stackIntegerValue: 4.
+ 	bufOop := interpreterProxy stackValue: 5.
- 	bufOop := interpreterProxy stackObjectValue: 5.
  	interpreterProxy failed ifTrue:[^nil].
+ 	((interpreterProxy isBytes: mOop)
+ 	and: [(interpreterProxy isBytes: bufOop)
+ 	and: [(interpreterProxy byteSizeOf: mOop) = 256
+ 	and: [startIndex > 0 and: [startIndex <= (bufSize := interpreterProxy byteSizeOf: bufOop)
+ 	and: [stopIndex >= startIndex and: [stopIndex <= bufSize]]]]]]) ifFalse:
+ 		[^interpreterProxy primitiveFail].
- 	((interpreterProxy isBytes: mOop) and:[interpreterProxy isBytes: bufOop])
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	(interpreterProxy byteSizeOf: mOop) = 256
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	bufSize := interpreterProxy byteSizeOf: bufOop.
- 	(startIndex > 0 and:[startIndex <= bufSize])
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	(stopIndex >= startIndex and:[stopIndex <= bufSize])
- 		ifFalse:[^interpreterProxy primitiveFail].
  	m := interpreterProxy firstIndexableField: mOop.
  	buffer := interpreterProxy firstIndexableField: bufOop.
  	startIndex-1 to: stopIndex-1 do:[:i|
  		x := (x + 1) bitAnd: 255.
  		a := m at: x.
  		y := (y + a) bitAnd: 255.
  		b := m at: y.
  		m at: x put: b.
  		m at: y put: a.
  		mask := m at: ((a + b) bitAnd: 255).
  		buffer at: i put: ((buffer at: i) bitXor: mask).
  	].
  	ptOop := interpreterProxy instantiateClass: interpreterProxy classPoint indexableSize: 0.
+ 	self cppIf: #SPURVM
+ 		ifTrue:
+ 			[xOop := interpreterProxy positive32BitIntegerFor: x.
+ 			yOop := interpreterProxy positive32BitIntegerFor: y.
+ 			(ptOop isNil or: [xOop isNil or: [yOop isNil]]) ifTrue:
+ 				[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 			interpreterProxy storePointer: 0 ofObject: ptOop withValue: xOop.
+ 			interpreterProxy storePointer: 1 ofObject: ptOop withValue: yOop]
+ 		ifFalse:
+ 			[interpreterProxy pushRemappableOop: ptOop.
+ 			xOop := interpreterProxy positive32BitIntegerFor: x.
+ 			interpreterProxy pushRemappableOop: xOop.
+ 			yOop := interpreterProxy positive32BitIntegerFor: y.
+ 			xOop := interpreterProxy popRemappableOop.
+ 			ptOop := interpreterProxy popRemappableOop.
+ 			interpreterProxy storePointer: 0 ofObject: ptOop withValue: xOop.
+ 			interpreterProxy storePointer: 1 ofObject: ptOop withValue: yOop].
+ 	^interpreterProxy methodReturnValue: ptOop!
- 	interpreterProxy pushRemappableOop: ptOop.
- 	xOop := interpreterProxy positive32BitIntegerFor: x.
- 	interpreterProxy pushRemappableOop: xOop.
- 	yOop := interpreterProxy positive32BitIntegerFor: y.
- 	xOop := interpreterProxy popRemappableOop.
- 	ptOop := interpreterProxy popRemappableOop.
- 	interpreterProxy storePointer: 0 ofObject: ptOop withValue: xOop.
- 	interpreterProxy storePointer: 1 ofObject: ptOop withValue: yOop.
- 	interpreterProxy pop: interpreterProxy methodArgumentCount + 1.
- 	^interpreterProxy push: ptOop.
- !

Item was changed:
  ----- Method: CroquetPlugin>>primitiveAdj3 (in category 'transforms') -----
  primitiveAdj3
  	"Computes the adjoint of the Matrix4x4 receiver,
  	placing the results the the Matrix4x4 argument,
  	"
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)>
+ 	|
+ 		srcOop src
- 	| 	
- 		argc 
- 		srcOop src 
  		dstOop dst
+ 		m11 m12 m13 m21 m22 m23 m31 m32 m33
+ 		c11 c12 c13 c21 c22 c23 c31 c32 c33  
- 		m11 m12 m13 m21 m22 m23 m31 m32 m33 
- 		c11 c12 c13 c21 c22 c23 c31 c32 c33 
- 		  
  	|
- 	<export: true>
- 	<inline: true>
  	<var: #c11 declareC: 'const int c11 = 0'>
  	<var: #c12 declareC: 'const int c12 = 1'>
  	<var: #c13 declareC: 'const int c13 = 2'>
  	"<var: #c14 declareC: 'const int c14 = 3'>"
  	<var: #c21 declareC: 'const int c21 = 4'>
  	<var: #c22 declareC: 'const int c22 = 5'>
  	<var: #c23 declareC: 'const int c23 = 6'>
  	"<var: #c24 declareC: 'const int c24 = 7'>"
  	<var: #c31 declareC: 'const int c31 = 8'>
  	<var: #c32 declareC: 'const int c32 = 9'>
  	<var: #c33 declareC: 'const int c33 = 10'>
  	"<var: #c34 declareC: 'const int c34 = 11'>"
+ 	<var: #m11 type: #double>
+ 	<var: #m12 type: #double>
+ 	<var: #m13 type: #double>
+ 	<var: #m21 type: #double>
+ 	<var: #m22 type: #double>
+ 	<var: #m23 type: #double>
+ 	<var: #m31 type: #double>
+ 	<var: #m32 type: #double>
+ 	<var: #m33 type: #double>
- 	<var: #src type: 'float *'>
- 	<var: #dst type: 'float *'>
- 	<var: #m11 type:  'double'>
- 	<var: #m12 type:  'double'>
- 	<var: #m13 type:  'double'>
- 	<var: #m21 type:  'double'>
- 	<var: #m22 type:  'double'>
- 	<var: #m23 type:  'double'>
- 	<var: #m31 type:  'double'>
- 	<var: #m32 type:  'double'>
- 	<var: #m33 type:  'double'>
  
  	"then we need the following no-op to make Smalltalk shut up about vars not being initted."
  	self cCode: '' inSmalltalk: [ 
  		c11 := 0. 
  		c12 := 1.
  		c13 := 2.
  		"c14 := 3."
  		c21 := 4.
  		c22 := 5.
  		c23 := 6.
  		"c24 := 7."
  		c31 := 8.
  		c32 := 9.
  		c33 := 10.
  		"c34 := 11."
  	].
  
  	"NOTE: the bottom row of a OpenGL-ordered matrix is always 0 0 0 1, 
  	so we don't need consts here for those elements."
  
+ 	srcOop := interpreterProxy stackObjectValue: 1.	
+ 	dstOop := interpreterProxy stackObjectValue: 0.
+ 	interpreterProxy failed ifTrue:
+ 		[^nil].
+ 	src := self cCoerce: (interpreterProxy firstIndexableField: srcOop) to: #'float *'.
+ 	dst := self cCoerce: (interpreterProxy firstIndexableField: dstOop) to: #'float *'.
- 	"do the dance to get our receiver and argument"
- 	argc := interpreterProxy methodArgumentCount.
- 	argc = 1
- 		ifFalse:[^interpreterProxy primitiveFail].
  
- 	"stackArgvObject is something I added to Interpreter, but since it's not in there yet,
- 	this won't compile - use it when it's there.  Yes, it would be nice if Smalltalk had #ifdefs..."
- 	self flag: #stackArgv.
- "
- 	srcOop := interpreterProxy stackArgvObject: 0.	
- 	src := interpreterProxy firstIndexableField: srcOop.
- 
- 	dstOop := interpreterProxy stackArgvObject: 1.
- 	dst := interpreterProxy firstIndexableField: dstOop.
- "
- 	srcOop := interpreterProxy stackObjectValue: argc.	
- 	src := interpreterProxy firstIndexableField: srcOop.
- 
- 	dstOop := interpreterProxy stackObjectValue: (argc - 1).
- 	dst := interpreterProxy firstIndexableField: dstOop.
- 
- 
  	"read in the source matrix 3x3, which contains the encoded rotation and scale factors"
  	m11 := src at: c11.
  	m12 := src at: c12.
  	m13 := src at: c13.
  	m21 := src at: c21.
  	m22 := src at: c22.
  	m23 := src at: c23.
  	m31 := src at: c31.
  	m32 := src at: c32.
  	m33 := src at: c33.
  
  	"do the actual work"
  
  	"compute our cofactors and transpose.  adj = transpose of cofactors"
  	dst at: c11 put:  ((m22 * m33) - (m23 *  m32)) .
  	dst at: c21 put: (0.0 - ((m21 * m33) - (m23 * m31))).
  	dst at: c31 put: ((m21 * m32) - (m22 * m31)).
  
  	dst at: c12 put: (0.0 - ((m12 * m33) - (m13 * m32))).
  	dst at: c22 put: ((m11 * m33) - (m13 * m31)).
  	dst at: c32 put: (0.0 - ((m11 * m32) - (m12 * m31))).
  
  	dst at: c13 put: ((m12 * m23) - (m13 * m22)).
  	dst at: c23 put: (0.0 - ((m11 * m23) - (m13 * m21))).
  	dst at: c33 put: ((m11 * m22) - (m12 * m21)).
  	
+ 	^interpreterProxy methodReturnValue: dstOop!
- 	interpreterProxy pop: argc + 1 thenPush: dstOop
- !

Item was changed:
  ----- Method: CroquetPlugin>>primitiveDet3 (in category 'transforms') -----
  primitiveDet3
  	"Computes the determinant of the upper 3x3 of a Matrix4x4"
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)>
+ 	| srcOop src m11 m12 m13 m21 m22 m23 m31 m32 m33 |
+ 	<var: #m11 type: #double>
+ 	<var: #m12 type: #double>
+ 	<var: #m13 type: #double>
+ 	<var: #m21 type: #double>
+ 	<var: #m22 type: #double>
+ 	<var: #m23 type: #double>
+ 	<var: #m31 type: #double>
+ 	<var: #m32 type: #double>
+ 	<var: #m33 type: #double>
- 	| argc  srcOop src det m11 m12 m13 m21 m22 m23 m31 m32 m33 |
- 	<export: true>
- 	<inline: true>
- 	<var: #src type: 'float *'>
- 	<var: #m11 type:  'double'>
- 	<var: #m12 type:  'double'>
- 	<var: #m13 type:  'double'>
- 	<var: #m21 type:  'double'>
- 	<var: #m22 type:  'double'>
- 	<var: #m23 type:  'double'>
- 	<var: #m31 type:  'double'>
- 	<var: #m32 type:  'double'>
- 	<var: #m33 type:  'double'>
- 	<var: #det type: 'double'>
  
- 	argc := interpreterProxy methodArgumentCount.
- 	argc = 0
- 		ifFalse:[^interpreterProxy primitiveFail].
- 
- 
  	"
  		Load element vars using C version of Matrix4x4 storage, as 0-based, 1-dimensional array:
  			0 1 2 3
  			4 5 6 7
  			8 9 10 11
  	"
+ 	srcOop := interpreterProxy stackObjectValue: 0.	
+ 	interpreterProxy failed ifTrue:
+ 		[^nil].
+ 	src := self cCoerce: (interpreterProxy firstIndexableField: srcOop) to: #'float *'.
  
- 	"stackArgvObject is something I added to Interpreter, but since it's not in there yet,
- 	this won't compile - use it when it's there.  Yes, it would be nice if Smalltalk had #ifdefs..."
- 	self flag: #stackArgv.
- "
- 	srcOop := interpreterProxy stackArgvObject: 0.	
- 	src := interpreterProxy firstIndexableField: srcOop.
- "
- 	srcOop := interpreterProxy stackObjectValue: argc.	
- 	src := interpreterProxy firstIndexableField: srcOop.
- 
- 
  	m11 := src at: 0.
  	m12 := src at: 1.
  	m13 := src at: 2.
  	m21 := src at: 4.
  	m22 := src at: 5.
  	m23 := src at: 6.
  	m31 := src at: 8.
  	m32 := src at: 9.
  	m33 := src at: 10.
  
+ 	^interpreterProxy methodReturnFloat: (m11 * ((m22 * m33) - (m23 * m32)))
+ 										+ (m12 * ((m23 * m31) - (m21 * m33)))
+ 										+ (m13 * ((m21 * m32) - (m22 * m31)))
- 
- 	"do the actual work"
- 	det := 
- 		( m11 * ((m22 * m33) - (m23 * m32))) +
- 			(m12 * ((m23 * m31) - (m21 * m33))) +
- 				(m13 * ((m21 * m32) - (m22 * m31))).
- 
- 	
- 	interpreterProxy pop: argc + 1.
- 	^interpreterProxy pushFloat: det.
  !

Item was changed:
  ----- Method: CroquetPlugin>>primitiveGatherEntropy (in category 'cryptography') -----
  primitiveGatherEntropy
  	"Primitive. Gather good random entropy from a system source."
- 	| bufOop bufSize bufPtr okay |
  	<export: true>
+ 	| bufOop |
+ 	bufOop := interpreterProxy stackValue: 0.
+ 	((interpreterProxy isBytes: bufOop)
+ 	 and: [self ioGatherEntropy: (interpreterProxy firstIndexableField: bufOop) _: (interpreterProxy byteSizeOf: bufOop)]) ifFalse:
+ 		[^interpreterProxy primitiveFail].
+ 	^interpreterProxy methodReturnBool: true!
- 	<var: 'bufPtr' type: 'void *'>
- 	(interpreterProxy methodArgumentCount = 1)
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	bufOop := interpreterProxy stackObjectValue: 0.
- 	interpreterProxy failed ifTrue:[^nil].
- 	(interpreterProxy isBytes: bufOop)
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	bufSize := interpreterProxy byteSizeOf: bufOop.
- 	bufPtr := interpreterProxy firstIndexableField: bufOop.
- 	okay := self cCode: 'ioGatherEntropy(bufPtr, bufSize)' inSmalltalk:[bufPtr. bufSize. false].
- 	okay ifFalse:[^interpreterProxy primitiveFail].
- 	interpreterProxy pop: interpreterProxy methodArgumentCount + 1.
- 	^interpreterProxy pushBool: true.!

Item was changed:
  ----- Method: CroquetPlugin>>primitiveInplaceHouseHolderInvert (in category 'transforms') -----
  primitiveInplaceHouseHolderInvert
  	"Primitive. Perform an inplace house holder matrix inversion"
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)>
  	| rcvr d x sigma beta sum s m |
+ 	<var: #rcvr type: #'float *'>
- 	<export: true>
- 	<var: #rcvr declareC:'float *rcvr'>
  	<var: #m declareC:'double m[4][4]'>
  	<var: #x declareC:'double x[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }'>
  	<var: #d declareC:'double d[4][4]'>
+ 	<var: #sigma type: #double>
+ 	<var: #beta type: #double>
+ 	<var: #sum type: #double>
+ 	<var: #s type: #double>
- 	<var: #sigma declareC:'double sigma'>
- 	<var: #beta declareC:'double beta'>
- 	<var: #sum declareC:'double sum'>
- 	<var: #s declareC:'double s'>
  
  	self cCode:'' inSmalltalk:[
  		m := CArrayAccessor on: 
  				((1 to: 4) collect:[:i| CArrayAccessor on: (Array new: 4)]).
  		x := CArrayAccessor on: (Array
  				with: (CArrayAccessor on: #(1.0 0.0 0.0 0.0) copy)
  				with: (CArrayAccessor on: #(0.0 1.0 0.0 0.0) copy)
  				with: (CArrayAccessor on: #(0.0 0.0 1.0 0.0) copy)
  				with: (CArrayAccessor on: #(0.0 0.0 0.0 1.0) copy)).
  		d := CArrayAccessor on: 
  				((1 to: 4) collect:[:i| CArrayAccessor on: (Array new: 4)]).
  	].
  	rcvr := self stackMatrix: 0.
+ 	rcvr ifNil:
+ 		[^interpreterProxy primitiveFail].
  	0 to: 3 do:[:i| 0 to: 3 do:[:j|
  		(m at: i) at: j put: (rcvr at: i*4+j)]].
  	0 to: 3 do:[:j|
  		sigma := 0.0.
  		j to: 3 do:[:i| sigma := sigma + (((m at: i) at: j)  * ((m at: i) at: j))].
  		sigma < 1.0e-10 ifTrue:[^interpreterProxy primitiveFail]. "matrix is singular"
  		(((m at: j) at: j) < 0.0) 
  			ifTrue:[ s:= sigma sqrt]
  			ifFalse:[ s:= 0.0 - sigma sqrt].
  		0 to: 3 do:[:r| (d at: j) at: r put: s].
  		beta := 1.0 / ( s * ((m at: j) at: j) - sigma).
  		(m at: j) at: j put: (((m at: j) at: j) - s).
  		"update remaining columns"
  		j+1 to: 3 do:[:k|
  			sum := 0.0.
  			j to: 3 do:[:i| sum := sum + (((m at: i) at: j) * ((m at: i) at: k))].
  			sum := sum * beta.
  			j to: 3 do:[:i| 
  				(m at: i) at: k put: (((m at: i) at: k) + (((m at: i) at: j) * sum))]].
  		"update vector"
  		0 to: 3 do:[:r|
  			sum := 0.0.
  			j to: 3 do:[:i| 
  				sum := sum + (((x at: i) at: r) * ((m at: i) at: j))].
  			sum := sum * beta.
  			j to: 3 do:[:i| 
  				(x at: i) at: r put:(((x at: i) at: r) + (sum * ((m at: i) at: j)))].
  		].
  	].
  	"Now calculate result"
  	0 to: 3 do:[:r|
  		3 to: 0 by: -1 do:[:i|
  			i+1 to: 3 do:[:j|
  				(x at: i) at: r put: (((x at: i) at: r) - (((x at: j) at: r) * ((m at: i) at: j))) ].
  			(x at: i) at: r put: (((x at: i) at: r) / ((d at: i) at: r))].
  	].
  	0 to: 3 do:[:i| 0 to: 3 do:[:j|
  		rcvr at: i*4+j put: (self cCoerce: ((x at: i) at: j) to:'float')]].
  	"Return receiver"
  	^nil!

Item was changed:
  ----- Method: CroquetPlugin>>primitiveInverseByAdjoint (in category 'transforms') -----
  primitiveInverseByAdjoint
  	"Computes the inverse of the Matrix4x4 receiver, using the 'classical adjoint' method,
  	placing the results the the Matrix4x4 argument,
  	"
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)>
+ 	|
+ 		srcOop src
- 	| 	
- 		srcOop src 
  		dstOop dst
+ 		det
+ 		m11 m12 m13 m21 m22 m23 m31 m32 m33
+ 		c11 c12 c13 c14 c21 c22 c23 c24 c31 c32 c33 c34
+ 		x y z
+ 	 |
- 		det 
- 		m11 m12 m13 m21 m22 m23 m31 m32 m33 
- 		c11 c12 c13 c14 c21 c22 c23 c24 c31 c32 c33 c34 
- 		x y z  
- 	argc |
- 	<export: true>
- 	<inline: true>
  	<var: #c11 declareC: 'const int c11 = 0'>
  	<var: #c12 declareC: 'const int c12 = 1'>
  	<var: #c13 declareC: 'const int c13 = 2'>
  	<var: #c14 declareC: 'const int c14 = 3'>
  	<var: #c21 declareC: 'const int c21 = 4'>
  	<var: #c22 declareC: 'const int c22 = 5'>
  	<var: #c23 declareC: 'const int c23 = 6'>
  	<var: #c24 declareC: 'const int c24 = 7'>
  	<var: #c31 declareC: 'const int c31 = 8'>
  	<var: #c32 declareC: 'const int c32 = 9'>
  	<var: #c33 declareC: 'const int c33 = 10'>
  	<var: #c34 declareC: 'const int c34 = 11'>
+ 	<var: #m11 type: #double>
+ 	<var: #m12 type: #double>
+ 	<var: #m13 type: #double>
+ 	<var: #m21 type: #double>
+ 	<var: #m22 type: #double>
+ 	<var: #m23 type: #double>
+ 	<var: #m31 type: #double>
+ 	<var: #m32 type: #double>
+ 	<var: #m33 type: #double>
+ 	<var: #x type:#double>
+ 	<var: #y type:#double>
+ 	<var: #z type:#double>
+ 	<var: #det type:#double>
- 	<var: #src type: 'float *'>
- 	<var: #dst type: 'float *'>
- 	<var: #m11 type:  'double'>
- 	<var: #m12 type:  'double'>
- 	<var: #m13 type:  'double'>
- 	<var: #m21 type:  'double'>
- 	<var: #m22 type:  'double'>
- 	<var: #m23 type:  'double'>
- 	<var: #m31 type:  'double'>
- 	<var: #m32 type:  'double'>
- 	<var: #m33 type:  'double'>
- 	<var: #x type: 'double'>
- 	<var: #y type: 'double'>
- 	<var: #z type: 'double'>
- 	<var: #det type: 'double'>
  
  	"then we need the following no-op to make Smalltalk shut up about vars not being initted."
  	self cCode: '' inSmalltalk: [ 
  		c11 := 0. 
  		c12 := 1.
  		c13 := 2.
  		c14 := 3.
  		c21 := 4.
  		c22 := 5.
  		c23 := 6.
  		c24 := 7.
  		c31 := 8.
  		c32 := 9.
  		c33 := 10.
  		c34 := 11.
  	].
  
  	"NOTE: the bottom row of a OpenGL-ordered matrix is always 0 0 0 1, 
  	so we don't need consts here for those elements."
  
  	"do the dance to get our receiver and argument"
+ 	srcOop := interpreterProxy stackValue: 1.
+ 	dstOop := interpreterProxy stackValue: 0.
+ 	interpreterProxy failed ifTrue:
+ 		[^nil].
+ 	src := self cCoerce: (interpreterProxy firstIndexableField: srcOop) to: #'float *'.
+ 	dst := self cCoerce: (interpreterProxy firstIndexableField: dstOop) to: #'float *'.
- 	argc := interpreterProxy methodArgumentCount.
- 	argc = 1
- 		ifFalse:[^interpreterProxy primitiveFail].
  
- 	"stackArgvObject is something I added to Interpreter, but since it's not in there yet,
- 	this won't compile - use it when it's there.  Yes, it would be nice if Smalltalk had #ifdefs..."
- 	self flag: #stackArgv.
- "
- 	srcOop := interpreterProxy stackArgvObject: 0.	
- 	src := interpreterProxy firstIndexableField: srcOop.
  
- 	dstOop := interpreterProxy stackArgvObject: 1.
- 	dst := interpreterProxy firstIndexableField: dstOop.
- "
- 	srcOop := interpreterProxy stackObjectValue: argc.	
- 	src := interpreterProxy firstIndexableField: srcOop.
- 
- 	dstOop := interpreterProxy stackObjectValue: (argc - 1).
- 	dst := interpreterProxy firstIndexableField: dstOop.
- 
- 
  	"read in the source matrix 3x3, which contains the encoded rotation and scale factors"
  	m11 := src at: c11.
  	m12 := src at: c12.
  	m13 := src at: c13.
  	m21 := src at: c21.
  	m22 := src at: c22.
  	m23 := src at: c23.
  	m31 := src at: c31.
  	m32 := src at: c32.
  	m33 := src at: c33.
  
  	"read in the source translation vector"
  	x := src at: c14.
  	y := src at: c24.
  	z := src at: c34.
  
  	"do the actual work"
  
  	"first, compute the determinant of the upper 3x3 of the source"
  	det := 
  		( m11 * ((m22 * m33) - (m23 * m32))) +
  			(m12 * ((m23 * m31) - (m21 * m33))) +
  				(m13 * ((m21 * m32) - (m22 * m31))).
  
  	"Compute the classical adjunct of the source, and divide by the source determinant
  	storing in the destination.  adjoint = transpose of cofactors, so we'll transpose as we store."
  
  	det := 1 / det.		"let's make div by det a multiply"
  	dst at: c11 put:  ((m22 * m33) - (m23 *  m32)) * det .
  	dst at: c21 put: (0.0 - ((m21 * m33) - (m23 * m31))) * det.
  	dst at: c31 put: ((m21 * m32) - (m22 * m31)) * det.
  
  	dst at: c12 put: (0.0 - ((m12 * m33) - (m13 * m32))) * det.
  	dst at: c22 put: ((m11 * m33) - (m13 * m31)) * det.
  	dst at: c32 put: (0.0 - ((m11 * m32) - (m12 * m31))) * det.
  
  	dst at: c13 put: ((m12 * m23) - (m13 * m22)) * det.
  	dst at: c23 put: (0.0 - ((m11 * m23) - (m13 * m21))) * det.
  	dst at: c33 put: ((m11 * m22) - (m12 * m21)) * det.
  	
  	"finally, apply the inversed rotation transform to our translation"
  	
  	"read in the source matrix 3x3"
  	m11 := dst at: c11.
  	m12 := dst at: c12.
  	m13 := dst at: c13.
  	m21 := dst at: c21.
  	m22 := dst at: c22.
  	m23 := dst at: c23.
  	m31 := dst at: c31.
  	m32 := dst at: c32.
  	m33 := dst at: c33.
  
  	dst at: c14 put: 0.0 - ((x * m11) + (y * m12) + (z * m13)).
  	dst at: c24 put: 0.0 - ((x * m21) + (y * m22) + (z * m23)).
  	dst at: c34 put: 0.0 - ((x * m31) + (y * m32) + (z * m33)).
  
+ 	^interpreterProxy methodReturnValue: dstOop!
- 	interpreterProxy pop: argc + 1.
- 	^interpreterProxy push: dstOop.
- !

Item was changed:
  ----- Method: CroquetPlugin>>primitiveMD5Transform (in category 'cryptography') -----
  primitiveMD5Transform
  	"Perform an MD5 transform of input"
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)> "Align in case the compiler identifies and generates vector instructions"
+ 	| bufOop hashOop |
+ 	hashOop := interpreterProxy stackValue: 0.
+ 	bufOop := interpreterProxy stackValue: 1.
+ 	((interpreterProxy isWords: hashOop) and: [(interpreterProxy slotSizeOf: hashOop) = 4
+ 	and: [(interpreterProxy isWords: bufOop) and: [(interpreterProxy slotSizeOf: bufOop) = 16]]])
+ 		ifFalse:
+ 			[^interpreterProxy primitiveFail].
- 	| bufOop hashOop hash buffer |
- 	<export: true>
- 	<var: 'hash' type: 'unsigned int *'>
- 	<var: 'buffer' type: 'unsigned int *'>
- 	interpreterProxy methodArgumentCount = 2 
- 		ifFalse:[^interpreterProxy primitiveFail].
  
+ 	self MD5Transform: (interpreterProxy firstIndexableField: hashOop) _: (interpreterProxy firstIndexableField: bufOop).
+ 	^interpreterProxy methodReturnValue: bufOop!
- 	hashOop := interpreterProxy stackObjectValue: 0.
- 	((interpreterProxy isWords: hashOop) and:[(interpreterProxy slotSizeOf: hashOop) = 4])
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	hash := interpreterProxy firstIndexableField: hashOop.
- 
- 	bufOop := interpreterProxy stackObjectValue: 1.
- 	((interpreterProxy isWords: bufOop) and:[(interpreterProxy slotSizeOf: bufOop) = 16])
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	buffer := interpreterProxy firstIndexableField: bufOop.
- 
- 
- 	self cCode:'MD5Transform(hash, buffer)' inSmalltalk:[
- 		hash. buffer. 
- 		^interpreterProxy primitiveFail].
- 	"Pop args; return buffer"
- 	interpreterProxy pop: interpreterProxy methodArgumentCount+1.
- 	^interpreterProxy push: bufOop.!

Item was changed:
  ----- Method: CroquetPlugin>>primitiveOptimizeVertexIndicesForCacheLocality (in category 'mesh processing') -----
  primitiveOptimizeVertexIndicesForCacheLocality
  	"Given a list of integer indices for rendering a triangle-mesh in indexed-triangles mode, reorganize the indices in-place to provide better vertex cache locality.
  	We use Tom Forsyth's algorithm:
  		http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
  	... and the MIT-licensed implementation by Michael Georgoulpoulos at:
  		http://code.google.com/p/vcacne/"
- 	| indicesOop indices byteSize triCount result |
  	<export: true>
+ 	| indicesOop byteSize triCount |
- 	<inline: true>
- 	<var: #indices type: 'void *'>
  
+ 	indicesOop := interpreterProxy stackValue: 0.
- 	"Get the oop of the IntegerArray containing the indices."
- 	(interpreterProxy methodArgumentCount = 1) ifFalse: [^interpreterProxy primitiveFail].
- 	indicesOop := interpreterProxy stackObjectValue: 0.
- 	interpreterProxy failed ifTrue: [^nil].
  	(interpreterProxy isWords: indicesOop) ifFalse: [^interpreterProxy primitiveFail].
  	
  	"Ensure that the number of indices is a multiple of 3."
  	byteSize := interpreterProxy byteSizeOf: indicesOop.
+ 	triCount := byteSize // 12.
- 	triCount := byteSize / 12.
  	(triCount * 12) = byteSize ifFalse: [^interpreterProxy primitiveFail].
+ 
+ 	"N.B. as of 8/2021 optimizeVertexIndices is simply a stub."
+ 	(self optimizeVertexIndices: (interpreterProxy firstIndexableField: indicesOop) _: triCount) ~= 0 ifTrue:
+ 		[^interpreterProxy primitiveFail].
+ 	^interpreterProxy methodReturnReceiver!
- 	
- 	"Get an int* to the indices, and optimize 'em."
- 	indices := interpreterProxy firstIndexableField: indicesOop.
- 	self touch: indices.
- 	interpreterProxy failed ifTrue: [^nil].
- 	result := self cCode: 'optimizeVertexIndices((int*)indices, triCount)'.
- 	result = 0 "success" ifFalse: [^interpreterProxy primitiveFail].
- 	^interpreterProxy pop: 1!

Item was changed:
  ----- Method: CroquetPlugin>>primitiveOrthoNormInverseMatrix (in category 'transforms') -----
  primitiveOrthoNormInverseMatrix
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)>
  	| srcOop dstOop src dst x y z rx ry rz |
- 	<export: true>
- 	<var: #src type: #'float *'>
- 	<var: #dst type: #'float *'>
  	<var: #x type: #double>
  	<var: #y type: #double>
  	<var: #z type: #double>
  	<var: #rx type: #double>
  	<var: #ry type: #double>
  	<var: #rz type: #double>
  
+ 	srcOop := interpreterProxy stackValue: 0.
+ 	((interpreterProxy isWords: srcOop) and:[(interpreterProxy slotSizeOf: srcOop) = 16]) ifFalse:
+ 		[^interpreterProxy primitiveFail].
- 	interpreterProxy methodArgumentCount = 0
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	srcOop := interpreterProxy stackObjectValue: 0.
- 	interpreterProxy failed ifTrue:[^nil].
- 	((interpreterProxy isWords: srcOop) and:[(interpreterProxy slotSizeOf: srcOop) = 16])
- 		ifFalse:[^interpreterProxy primitiveFail].
  	dstOop := interpreterProxy cloneObject: srcOop.
+ 	dstOop = 0 ifTrue:
+ 		[^interpreterProxy primitiveFail].
  	"reload srcOop in case of GC"
+ 	self cppIf: #SPURVM ifFalse: [srcOop := interpreterProxy stackValue: 0].
+ 	src := self cCoerce: (interpreterProxy firstIndexableField: srcOop) to: #'float *'.
+ 	dst := self cCoerce: (interpreterProxy firstIndexableField: dstOop) to: #'float *'.
- 	srcOop := interpreterProxy stackObjectValue: 0.
- 	src := interpreterProxy firstIndexableField: srcOop.
- 	dst := interpreterProxy firstIndexableField: dstOop.
  
  	"Transpose upper 3x3 matrix"
  	"dst at: 0 put: (src at: 0)."	dst at: 1 put: (src at: 4). 	dst at: 2 put: (src at: 8). 
  	dst at: 4 put: (src at: 1). 	"dst at: 5 put: (src at: 5)."	dst at: 6 put: (src at: 9). 
  	dst at: 8 put: (src at: 2). 	dst at: 9 put: (src at: 6). 	"dst at: 10 put: (src at: 10)."
  
  	"Compute inverse translation vector"
  	x := src at: 3.
  	y := src at: 7.
  	z := src at: 11.
  	rx := (x * (dst at: 0)) + (y * (dst at: 1)) + (z * (dst at: 2)).
  	ry := (x * (dst at: 4)) + (y * (dst at: 5)) + (z * (dst at: 6)).
  	rz := (x * (dst at: 8)) + (y * (dst at: 9)) + (z * (dst at: 10)).
  
+ 	dst at: 3 put: 0.0 - rx.
+ 	dst at: 7 put: 0.0 - ry.
+ 	dst at: 11 put: 0.0 - rz.
- 	dst at: 3 put: (self cCoerce: 0.0-rx to: #float).
- 	dst at: 7 put: (self cCoerce: 0.0-ry to: #float).
- 	dst at: 11 put: (self cCoerce: 0.0-rz to: #float).
  
+ 	^interpreterProxy methodReturnValue: dstOop!
- 	interpreterProxy pop: 1 thenPush: dstOop!

Item was changed:
  ----- Method: CroquetPlugin>>primitiveTransformDirection (in category 'transforms') -----
  primitiveTransformDirection
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)>
  	| x y z rx ry rz matrix vertex v3Oop |
+ 	<var: #x type: #double>
+ 	<var: #y type: #double>
+ 	<var: #z type: #double>
+ 	<var: #rx type: #double>
+ 	<var: #ry type: #double>
+ 	<var: #rz type: #double>
- 	<export: true>
- 	<var: #vertex declareC:'float *vertex'>
- 	<var: #matrix declareC:'float *matrix'>
- 	<var: #x declareC:'double x'>
- 	<var: #y declareC:'double y'>
- 	<var: #z declareC:'double z'>
- 	<var: #rx declareC:'double rx'>
- 	<var: #ry declareC:'double ry'>
- 	<var: #rz declareC:'double rz'>
  
- 	interpreterProxy methodArgumentCount = 1
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	v3Oop := interpreterProxy stackObjectValue: 0.
- 	interpreterProxy failed ifTrue:[^nil].
- 	((interpreterProxy isWords: v3Oop) and:[(interpreterProxy slotSizeOf: v3Oop) = 3])
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	vertex := interpreterProxy firstIndexableField: v3Oop.
  	matrix := self stackMatrix: 1.
+ 	v3Oop := interpreterProxy stackValue: 0.
+ 	(matrix notNil and: [(interpreterProxy isWords: v3Oop) and:[(interpreterProxy slotSizeOf: v3Oop) = 3]]) ifFalse:
+ 		[^interpreterProxy primitiveFail].
+ 	vertex := self cCoerce: (interpreterProxy firstIndexableField: v3Oop) to: #'float *'.
- 	(matrix == nil) ifTrue:[^interpreterProxy primitiveFail].
  
  	x := vertex at: 0.
  	y := vertex at: 1.
  	z := vertex at: 2.
  
  	rx := (x * (matrix at: 0)) + (y * (matrix at: 1)) + (z * (matrix at: 2)).
  	ry := (x * (matrix at: 4)) + (y * (matrix at: 5)) + (z * (matrix at: 6)).
  	rz := (x * (matrix at: 8)) + (y * (matrix at: 9)) + (z * (matrix at: 10)).
  
  	v3Oop := interpreterProxy cloneObject: v3Oop.
+ 	v3Oop = 0 ifTrue:
+ 		[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 	vertex := self cCoerce: (interpreterProxy firstIndexableField: v3Oop) to: #'float *'.
- 	vertex := interpreterProxy firstIndexableField: v3Oop.
  
+ 	vertex at: 0 put: rx.
+ 	vertex at: 1 put: ry.
+ 	vertex at: 2 put: rz.
- 	vertex at: 0 put: (self cCoerce: rx to: 'float').
- 	vertex at: 1 put: (self cCoerce: ry to:'float').
- 	vertex at: 2 put: (self cCoerce: rz to: 'float').
  
+ 	^interpreterProxy methodReturnValue: v3Oop!
- 	interpreterProxy pop: 2.
- 	^interpreterProxy push: v3Oop.
- !

Item was changed:
  ----- Method: CroquetPlugin>>primitiveTransformMatrixWithInto (in category 'transforms') -----
  primitiveTransformMatrixWithInto
  	"Transform two matrices into the third"
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)>
  	| m1 m2 m3 |
- 	<export: true>
- 	<inline: false>
- 	<var: #m1 declareC:'float *m1'>
- 	<var: #m2 declareC:'float *m2'>
- 	<var: #m3 declareC:'float *m3'>
  
  	m3 := self stackMatrix: 0.
  	m2 := self stackMatrix: 1.
  	m1 := self stackMatrix: 2.
+ 	(m1 isNil or: [m2 isNil or: [m3 isNil
+ 	 or: [m2 = m3]]]) ifTrue:
+ 		[^interpreterProxy primitiveFail].
- 	(m1 = nil) | (m2 = nil) | (m3 = nil) 
- 		ifTrue:[^interpreterProxy primitiveFail].
- 	m2 == m3 ifTrue:[^interpreterProxy primitiveFail].
  	self transformMatrix: m1 with: m2 into: m3.
+ 	^interpreterProxy methodReturnReceiver!
- 	^interpreterProxy pop: 3. "Leave rcvr on stack"!

Item was changed:
  ----- Method: CroquetPlugin>>primitiveTransformVector3 (in category 'transforms') -----
  primitiveTransformVector3
+ 	<export: true flags: #(FastCPrimitiveFlag FastCPrimitiveAlignForFloatsFlag)>
  	| x y z rx ry rz rw matrix vertex v3Oop |
+ 	<var: #x type: #double>
+ 	<var: #y type: #double>
+ 	<var: #z type: #double>
+ 	<var: #rx type: #double>
+ 	<var: #ry type: #double>
+ 	<var: #rz type: #double>
+ 	<var: #rw type: #double>
- 	<export: true>
- 	<var: #vertex declareC:'float *vertex'>
- 	<var: #matrix declareC:'float *matrix'>
- 	<var: #x declareC:'double x'>
- 	<var: #y declareC:'double y'>
- 	<var: #z declareC:'double z'>
- 	<var: #rx declareC:'double rx'>
- 	<var: #ry declareC:'double ry'>
- 	<var: #rz declareC:'double rz'>
- 	<var: #rw declareC:'double rw'>
  
- 	interpreterProxy methodArgumentCount = 1
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	v3Oop := interpreterProxy stackObjectValue: 0.
- 	interpreterProxy failed ifTrue:[^nil].
- 	((interpreterProxy isWords: v3Oop) and:[(interpreterProxy slotSizeOf: v3Oop) = 3])
- 		ifFalse:[^interpreterProxy primitiveFail].
- 	vertex := interpreterProxy firstIndexableField: v3Oop.
  	matrix := self stackMatrix: 1.
+ 	v3Oop := interpreterProxy stackValue: 0.
+ 	(matrix notNil and: [(interpreterProxy isWords: v3Oop) and:[(interpreterProxy slotSizeOf: v3Oop) = 3]]) ifFalse:
+ 		[^interpreterProxy primitiveFail].
+ 	vertex := self cCoerce: (interpreterProxy firstIndexableField: v3Oop) to: #'float *'.
- 	(matrix == nil) ifTrue:[^interpreterProxy primitiveFail].
  
  	x := vertex at: 0.
  	y := vertex at: 1.
  	z := vertex at: 2.
  
  	rx := (x * (matrix at: 0)) + (y * (matrix at: 1)) + (z * (matrix at: 2)) + (matrix at: 3).
  	ry := (x * (matrix at: 4)) + (y * (matrix at: 5)) + (z * (matrix at: 6)) + (matrix at: 7).
  	rz := (x * (matrix at: 8)) + (y * (matrix at: 9)) + (z * (matrix at: 10)) + (matrix at: 11).
  	rw := (x * (matrix at: 12)) + (y * (matrix at: 13)) + (z * (matrix at: 14)) + (matrix at: 15).
  
  	v3Oop := interpreterProxy cloneObject: v3Oop.
+ 	v3Oop = 0 ifTrue:
+ 		[^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 	vertex := self cCoerce: (interpreterProxy firstIndexableField: v3Oop) to: #'float *'.
- 	vertex := interpreterProxy firstIndexableField: v3Oop.
  
  	rw = 1.0 ifTrue:[
+ 		vertex at: 0 put: rx.
+ 		vertex at: 1 put: ry.
+ 		vertex at: 2 put: rz.
- 		vertex at: 0 put: (self cCoerce: rx to: 'float').
- 		vertex at: 1 put: (self cCoerce: ry to:'float').
- 		vertex at: 2 put: (self cCoerce: rz to: 'float').
  	] ifFalse:[
  		rw = 0.0 
  			ifTrue:[rw := 0.0]
  			ifFalse:[rw := 1.0 / rw].
+ 		vertex at: 0 put: rx * rw.
+ 		vertex at: 1 put: ry * rw.
+ 		vertex at: 2 put: rz * rw.
- 		vertex at: 0 put: (self cCoerce: rx*rw to:'float').
- 		vertex at: 1 put: (self cCoerce: ry*rw to:'float').
- 		vertex at: 2 put: (self cCoerce: rz*rw to: 'float').
  	].
+ 	^interpreterProxy methodReturnValue: v3Oop!
- 	interpreterProxy pop: 2.
- 	^interpreterProxy push: v3Oop.
- !

Item was changed:
  ----- Method: CroquetPlugin>>primitiveTriBoxIntersects (in category 'transforms') -----
  primitiveTriBoxIntersects
  	"Primitive. Answer whether an AABB intersects with a given triangle"
  	| minCorner maxCorner v0 v1 v2 result |
- 	<export: true>
- 	<var: #minCorner type: #'float *'>
- 	<var: #maxCorner type: #'float *'>
- 	<var: #v0 type: #'float *'>
- 	<var: #v1 type: #'float *'>
- 	<var: #v2 type: #'float *'>
  
- 	interpreterProxy methodArgumentCount = 5
- 		ifFalse:[^interpreterProxy primitiveFail].
  	v2 := self stackVector3: 0.
  	v1 := self stackVector3: 1.
  	v0 := self stackVector3: 2.
  	maxCorner := self stackVector3: 3.
  	minCorner := self stackVector3: 4.
  
+ 	(v0 isNil or: [v1 isNil or: [v2 isNil
+ 	 or: [maxCorner isNil or: [minCorner isNil]]]]) ifTrue:
+ 		[^interpreterProxy primitiveFail].
+ 	"N.B. as of 8/2021 triBoxOverlap is simply a stub."
+ 	result := self triBoxOverlap: minCorner _: maxCorner _: v0 _: v1 _: v2.
- 	result := self cCode:'triBoxOverlap(minCorner, maxCorner, v0, v1, v2)' 
- 				inSmalltalk:[minCorner. maxCorner. v0. v1. v2. -1].
  	result < 0 ifTrue:[^interpreterProxy primitiveFail].
+ 	^interpreterProxy methodReturnBool: result > 0!
- 
- 	interpreterProxy pop: 6. "args+rcvr"
- 	^interpreterProxy pushBool: result.!

Item was changed:
  ----- Method: CroquetPlugin>>stackMatrix: (in category 'transforms') -----
  stackMatrix: index
  	"Load a 4x4 transformation matrix from the interpreter stack.
  	Return a pointer to the matrix data if successful, nil otherwise."
+ 	<returnTypeC: #'float *'>
  	| oop |
+ 	<inline: #always>
+ 	oop := interpreterProxy stackValue: index.
+ 	^((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = 16]) ifTrue:
+ 		[self cCoerce: (interpreterProxy firstIndexableField: oop) to: #'float *']!
- 	<inline: false>
- 	<returnTypeC:'void*'>
- 	oop := interpreterProxy stackObjectValue: index.
- 	oop = nil ifTrue:[^nil].
- 	((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = 16])
- 		ifTrue:[^interpreterProxy firstIndexableField: oop].
- 	^nil!

Item was changed:
  ----- Method: CroquetPlugin>>stackVector3: (in category 'transforms') -----
  stackVector3: index
  	"Load a Vector3 from the interpreter stack.
  	Return a pointer to the float data if successful, nil otherwise."
+ 	<returnTypeC: #'float *'>
  	| oop |
+ 	<inline: #always>
+ 	oop := interpreterProxy stackValue: index.
+ 	^((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = 3]) ifTrue:
+ 		[self cCoerce: (interpreterProxy firstIndexableField: oop) to: #'float *']!
- 	<inline: false>
- 	<returnTypeC:'void*'>
- 	oop := interpreterProxy stackObjectValue: index.
- 	oop = nil ifTrue:[^nil].
- 	((interpreterProxy isWords: oop) and:[(interpreterProxy slotSizeOf: oop) = 3])
- 		ifTrue:[^interpreterProxy firstIndexableField: oop].
- 	^nil!

Item was changed:
  ----- Method: CroquetPlugin>>transformMatrix:with:into: (in category 'transforms') -----
  transformMatrix: src with: arg into: dst
  	"Transform src with arg into dst.
  	It is allowed that src == dst but not arg == dst"
+ 	<var: #src type: #'float *'>
+ 	<var: #arg type: #'float *'>
+ 	<var: #dst type: #'float *'>
  	| m1 m2 m3 c1 c2 c3 c4 |
+ 	<var: #m1 type: #'float *'>
+ 	<var: #m2 type: #'float *'>
+ 	<var: #m3 type: #'float *'>
- 	<var: #src declareC:'float *src'>
- 	<var: #arg declareC:'float *arg'>
- 	<var: #dst declareC:'float *dst'>
- 	<var: #m1 declareC:'float *m1'>
- 	<var: #m2 declareC:'float *m2'>
- 	<var: #m3 declareC:'float *m3'>
  
+ 	<var: #c1 type: #double>
+ 	<var: #c2 type: #double>
+ 	<var: #c3 type: #double>
+ 	<var: #c4 type: #double>
- 	<var: #c1 declareC:'double c1'>
- 	<var: #c2 declareC:'double c2'>
- 	<var: #c3 declareC:'double c3'>
- 	<var: #c4 declareC:'double c4'>
  
+ 	m1 := self cCoerce: src to: #'float *'.
+ 	m2 := self cCoerce: arg to: #'float *'.
+ 	m3 := self cCoerce: dst to: #'float *'.
- 	m1 := self cCoerce: src to:'float *'.
- 	m2 := self cCoerce: arg to: 'float *'.
- 	m3 := self cCoerce: dst to: 'float *'.
  
  	0 to: 3 do:[:i|
  
  		"Compute next row"
+ 		c1 :=	((m1 at: 0) * (m2 at: 0)) + ((m1 at: 1) * (m2 at: 4)) +
+ 				((m1 at: 2) * (m2 at: 8)) + ((m1 at: 3) * (m2 at: 12)).
- 		c1 := ((m1 at: 0) asFloat * (m2 at: 0) asFloat) + ((m1 at: 1) asFloat * (m2 at: 4) asFloat) +
- 			((m1 at: 2) asFloat * (m2 at: 8) asFloat) + ((m1 at: 3) asFloat * (m2 at: 12) asFloat).
  
+ 		c2 :=	((m1 at: 0) * (m2 at: 1)) + ((m1 at: 1) * (m2 at: 5)) +
+ 				((m1 at: 2) * (m2 at: 9)) + ((m1 at: 3) * (m2 at: 13)).
- 		c2 := ((m1 at: 0) asFloat * (m2 at: 1) asFloat) + ((m1 at: 1) asFloat * (m2 at: 5) asFloat) +
- 			((m1 at: 2) asFloat * (m2 at: 9) asFloat) + ((m1 at: 3) asFloat * (m2 at: 13) asFloat).
  
+ 		c3 :=	((m1 at: 0) * (m2 at: 2)) + ((m1 at: 1) * (m2 at: 6)) +
+ 				((m1 at: 2) * (m2 at: 10)) + ((m1 at: 3) * (m2 at: 14)).
- 		c3 := ((m1 at: 0) asFloat * (m2 at: 2) asFloat) + ((m1 at: 1) asFloat * (m2 at: 6) asFloat) +
- 			((m1 at: 2) asFloat * (m2 at: 10) asFloat) + ((m1 at: 3) asFloat * (m2 at: 14) asFloat).
  
+ 		c4 :=	((m1 at: 0) * (m2 at: 3)) + ((m1 at: 1) * (m2 at: 7)) +
+ 				((m1 at: 2) * (m2 at: 11)) + ((m1 at: 3) * (m2 at: 15)).
- 		c4 := ((m1 at: 0) asFloat * (m2 at: 3) asFloat) + ((m1 at: 1) asFloat * (m2 at: 7) asFloat) +
- 			((m1 at: 2) asFloat * (m2 at: 11) asFloat) + ((m1 at: 3) asFloat * (m2 at: 15) asFloat).
  
  		"Store result"
  		m3 at: 0 put: c1.
  		m3 at: 1 put: c2.
  		m3 at: 2 put: c3.
  		m3 at: 3 put: c4.
  
  		"Skip src and dst to next row"
  		m1 := m1 + 4.
  		m3 := m3 + 4.
  	].
  
  	^nil
  !




More information about the Vm-dev mailing list